tmux Kill-window 不会杀死子进程

tmux Kill-window 不会杀死子进程

如果我这样做ctrl-c并且ctrl-d杀死窗格中的进程然后从 tmux 退出,那么所有子进程都会死亡。

但如果我这样做:

ctrl+b后接shift+%

然后选择 Y 杀死窗口,然后进程保持活动状态。知道如何确保窗口被杀死时进程也被杀死吗?

答案1

Ctrl+ckill-window

通常使用Ctrl+c你(当stty -a显示intr = ^C)发送 SIGINT 到前台进程组中的进程。您似乎假设任何获得 SIGINT 的进程都会退出(被杀死),但一般情况下可能不会。

您提到了Ctrl+ d,所以 tmux 服务器和您想要终止的进程之间可能存在一个交互式 shell。在这种情况下,SIGINT 被发送到进程,而不是 shell;但即使 shell 得到了它,它也不会退出。 (我并不是说它总是这样;我是说它符合你的描述)。

因此,在Ctrl+进程终止后c,您可以按Ctrl+d退出 shell。

当您在 tmux 中终止一个窗口时,相应的伪终端将关闭,并且使用它们作为控制终端的进程会收到 SIGHUP。这样的进程可能会向其子进程发送 SIGHUP (对于 shell,请参见这个答案)。进程可能会忽略该信号(请参阅参考资料nohup)。即使它忽略该信号,如果它尝试使用不再存在的伪终端,它也可能(或可能不会)稍后死亡。

简而言之:

  • 您向相关进程发送 SIGINT 或 SIGHUP;
  • 是否以及如何对 SIGINT 或 SIGHUP 做出反应取决于进程

发送 SIGINT

进程可能会忽略 SIGINT。如果Ctrl+c为您正在处理的进程执行您想要的操作,那么也许在杀死窗口并发送 SIGHUP 之前向它们发送 SIGINT 就足够了;就像您在每个窗格中点击Ctrl+一样。c

以下命令在当前窗口的窗格中列出进程(tmux 服务器的直接子进程),获取各自的前台进程组并向每个进程发送 SIGINT:

tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{}

问题是这个管道也将收到 SIGINT,并且可能会提前终止。为了解决这个问题

  • 从其他地方运行命令并使用-t指定窗口,
  • 或者实现一些逻辑,因此排除管道的前台进程组,
  • 或在后台运行管道:

    tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{} &
    
  • 或使命令忽略信号:

    sh -c '
    trap "" SIGINT
    tmux list-panes -F "#{pane_pid}" | xargs ps -o tpgid= | xargs -I{} kill -s SIGINT -{}
    '
    

我认为这种方法很容易出现竞争条件;事情可能会在ps和之间发生变化kill。更好的(?)替代方法是将Ctrl+发送c到每个窗格:

tmux list-panes -F "#{pane_id}" | xargs -I {} tmux send-keys -t {} C-c &

使用此钩子使 tmux 向即将编辑的窗口中的每个窗格发送Ctrl+ :ckill-window

tmux set-hook before-kill-window 'run-shell "
   tmux list-panes -t \"#{window_id}\" -F \"##{pane_id}\" | xargs -I {} tmux send-keys -t {} C-c
"'

这看起来很糟糕,因为存在三个级别的引用,但它似乎在我的测试中仍然有效(尽管我还没有彻底测试)。的目的##是推迟 的扩展#{pane_id}。要点是工作#{window_id}时需要扩展run-shell,但必须生存并且只有在生成输出#{pane_id}时才扩展。list-panes

注意钩子覆盖kill-window但不是kill-pane,kill-sessionkill-server。也是kill-window不是只是kill-pane重复了几次,所以before-kill-pane 当窗格被强行破坏时,钩子肯定不会覆盖所有情况。还有respawn-pane -krespawn-window -k命令。


如果还不够怎么办?

进程可能不会在 SIGINT 时终止。作为tmux list-panes -F "#{pane_pid}"起点,您可以尝试获取要向其发送 SIGTERM(甚至 SIGKILL)的 PI​​D(和/或 PGID)列表。这种一般方法的主要问题是它可能会产生一个进程并完全断开它与其祖先和 tty 的连接。

因此,通常您可能无法跟踪源自给定 tmux 窗口的所有进程。

答案2

您没有提供足够的信息。

C-b %分割窗口,它不会杀死任何东西,所以你必须改变键绑定。你有什么绑定吗?或者你的意思是C-b &

终止窗格将关闭 pty,并且内核将向所有将 pty 作为控制终端的进程发送 SIGHUP,这将使它们退出,除非它们忽略它。

您到底在窗格中运行什么?这些进程是根本不退出还是变成了僵尸进程?

另外,了解您正在使用的 tmux 版本也会很有帮助。

相关内容