在继续之前请参阅这个未回答的问题: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 读取数据,这可能会导致多个错误。立即发送的命令行。