我while
在 tmux 状态栏中嵌入了一个无限循环 bash 脚本。在 ~/.tmux/conf 中:
set -g status-right '... #(path/loop.sh) ...'
Tmux 似乎使用sh -c
. tmux 启动后:
$ ps x | grep loop.sh
23433 pts/4 S+ 0:00 grep --color=auto loop.sh
31814 ? S 0:00 sh -c path/loop.sh
31818 ? S 0:00 /bin/bash path/loop.sh
tmux kill-session
终止sh -c
进程。如果我strace
这样做并终止会话:
$ strace -p 31814
strace: Process 31814 attached
wait4(-1, 0x7ffeacbfbf9c, 0, NULL) = ? ERESTARTSYS (To be restarted if SA_RESTART is set)
--- SIGTERM {si_signo=SIGTERM, si_code=SI_USER, si_pid=27643, si_uid=1000} ---
+++ killed by SIGTERM +++
但由于无限循环,子 shell 保持不变:
$ ps x | grep loop.sh
2443 pts/4 S+ 0:00 grep --color=auto loop.sh
31818 ? S 0:00 /bin/bash path/loop.sh
问题
我希望子 shell 在 tmux 会话结束后自动终止。有没有办法通过更改 tmux 设置或处理SIGTERM
发送到进程来做到这一点sh -c
?
(编辑:tmux版本是2.8)
答案1
是的,开始的子进程tmux -c "start process here"
似乎在相应的tmux
会话中存活下来。我仔细研究了tmux
广泛的手册页,有一段时间我希望在全球范围内设置tmux
命令的后钩可以有所帮助。后钩具有以下形式:
$ tmux set-hook -g after-session-closed your_cmd_here
在哪里“你的cmd_在这里”可以用来杀死生成无限循环的子进程。但这并没有帮助,因为“你的cmd_在这里”事实上必须是一个tmux
cmd而不是linux shell cmd。
相反,一个快速的技巧是在脚本的无限循环内添加一行 /path/loop.sh
,例如:
[ "x$(ps -e | grep tmux | grep -v grep)" = "x" ] && break
tmux
一旦的输出中没有显示任何活动进程,这将使您摆脱无限循环ps -ae
。相反,如果tmux
显示相关进程,则循环将继续不受影响。
实际上,对于您将退出会话但系统上tmux
仍有活动进程的极端情况,上述测试的更好版本是:man tmux
[ $(\ps -e | awk 'BEGIN {rv=0}; tolower($0) ~/tmux/ {if ($4 == "tmux") {rv=1}; exit} END {print rv}') == "1" ] && break
- 上面处理的是
tmux
出现在 的输出中\ps -e
但不作为主进程的情况,即不在 的输出行的位置 4 中ps -e
,而是作为正在运行的进程的参数,或者随意作为嵌入在的输出\ps -e
。 - 请注意我如何使用纯粹的形式,
ps
在 cmd 之前添加反斜杠 as\ps
。这是为了防止 cmd 的修改版本与awk
.例如,如果您使用的\ps -eF
是\ps -e
example,则需要更改$4
为$11
.
HTH。