我有一个大致如下所示的 Bash 脚本“脚本”:
#!/bin/bash
cmd1 | cmd2 | cmd3
当我做一个kill script
(或更准确地说,当我在 中做一个“停止脚本”时supervisord
),并不是所有的 cmd* 都被杀死了。我如何确保它们与生成它们的脚本一起被终止?
我有一个大致如下所示的 Bash 脚本“脚本”:
#!/bin/bash
cmd1 | cmd2 | cmd3
当我做一个kill script
(或更准确地说,当我在 中做一个“停止脚本”时supervisord
),并不是所有的 cmd* 都被杀死了。我如何确保它们与生成它们的脚本一起被终止?
Supervisord 有stopasgroup和killasgroup选项(默认为 false),它们决定是否将 SIGTERM/SIGKILL 信号传播到子进程。
[program:script]
command=script
stopasgroup=true
killasgroup=true
(这些配置变量都记录在http://supervisord.org/configuration.html。)
不确定如何使用supervisord
,但pkill
您可以使用-P
从父进程到所有子进程终止的选项。这是进程树(从我正在运行的 ssh 守护程序开始)。
$ pstree -a -p 1792
sshd,1792
├─sshd,27150
│ └─sshd,27153
│ └─zsh,27154
│ └─test.sh,27325 ./test.sh
│ └─cat,27326
└─sshd,27182
└─sshd,27184
└─zsh,27185
└─pstree,27357 -a -p 1792
在一个会话中,我有一个test.sh
pid 为 27325 的脚本,而在另一个会话中,我正在运行该命令pstree -a -p 1792
(因为sshd
有 pid 1792)
在我运行之后pkill -TERM -P 27325
:
$ pstree -a -p 1792
sshd,1792
├─sshd,27150
│ └─sshd,27153
│ └─zsh,27154
└─sshd,27182
└─sshd,27184
└─zsh,27185
└─pstree,27387 -a -p 1792
这个答案基本上是从stackoverflow上的另一个答案改写的:https ://stackoverflow.com/a/392155/263969
另一种解决方案是捕获 SIGTERM 并杀死陷阱代码中的所有孩子。
唯一的问题是,shell 仅在当前运行的命令完成后才为接收到的信号运行陷阱代码——所以在你的情况下,仅此一项是没有帮助的。
但是,如果 shell 处于“等待”状态,陷阱将以“异步”方式运行。
#!/usr/bin/env bash
trap 'kill 0' TERM
( cmd1 | cmd2 | cmd3 ) & wait
kill 0
向当前进程组中的所有进程发送 SIGTERM 。
注意:我在这里谈论 Bash。