Zsh/Tmux:等待子进程成功

Zsh/Tmux:等待子进程成功

在继续之前请参阅这个未回答的问题:Tmux:检查由发送键发送的命令的退出代码

tmux send-keys只需发送命令并成功退出,但repeat 5; do print This is a test; sleep 1; done仍继续作为子进程运行 - 而不是在子 shell 中。

如果我需要确保repeat 5; do print This is a test; sleep 1; done在做另一个之前完全完成tmux send-keys

我怎样才能用 zsh 实现这一点?

编辑:@Stéphane Chazelas:我想扩展或使问题更清楚:

如果 zsh 脚本包含多个send-keys命令,如下所示:

send-keys 'command1_run_as_subprocess_with_unpredictable_time_to_complete' Enter
send-keys 'command2_run_as_subprocess_with_unpredictable_time_to_complete' Enter
send-keys 'command3_run_as_subprocess_with_unpredictable_time_to_complete' Enter
<...>

每个都send-keys必须等待前一个完全完成才能运行。

您的解决方案如何应用于上述案例?:

typeset -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))

pid=$pane_pid[%0] # pid of process started in first pane

答案1

我想您可以等到 tmux 窗格中运行的 shell 再次从终端设备读取数据:

如果在 Linux 上,

until grep -qw tty_read "/proc/$pid/stack"; do sleep 1; done

其中$pid是该 shell 的进程 ID。

或者更有效且延迟更短zsh

zmodload zsh/zselect
until [[ $(</proc/$pid/stack) = *tty_read* ]] zselect -t 10

请注意,您需要/proc/sys/kernel/yama/ptrace_scope包含 0 才能正常工作(以便进程能够查看其他进程正在做什么)。请注意,将该值更改为 0(使用sudo sysctl -w kernel.yama.ptrace_scope=0)会稍微降低系统的安全性。

要获取 tmux 窗格 id 或索引和它在其中运行的进程的 pid 之间的映射,您可以执行以下操作:

typeset -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))

pid=$pane_pid[%0] # pid of process started in first pane

因此将两者结合起来:

zmodload zsh/zselect
wait_for_shell_on_pane_to_read_tty() {
  local pane=$1
  local -A pane_pid=($(for t (id index) tmux lsp -F "#{pane_$t} #{pane_pid}"))
  until [[ $(</proc/$pane_pid[$pane]/stack) = *tty_read* ]] zselect -t 10
}

pane=%0 # replace with the pane you want to send those commands to
        # see tmux lsp for the list of panes

for cmd (
  'repeat 5; do print This is a test; sleep 1; done'
  command1_run_as_subprocess_with_unpredictable_time_to_complete
  command2_run_as_subprocess_with_unpredictable_time_to_complete
  command3_run_as_subprocess_with_unpredictable_time_to_complete
) {
  wait_for_shell_on_pane_to_read_tty $pane
  tmux send-keys -t $pane $cmd Enter
}

请注意,由于我们按顺序发送这些命令行,它们之间没有延迟,因此在我们发送第一个命令(并且尚未执行它)后,窗格中的 shell 可能仍在从 tty 读取数据,这可能会导致多个错误。立即发送的命令行。

相关内容