我有一个Bash脚本“脚本”,大致如下:
#!/bin/bash
cmd1 | cmd2 | cmd3
当我执行kill script
时(或更确切地说,当我在supervisord
中执行“停止脚本”时),并非所有cmd *都被杀死。如何确保它们与产生它们的脚本一起终止?
答案 0 :(得分:6)
Supervisord有 stopasgroup 和 killasgroup 选项(默认为false),用于确定是否将SIGTERM / SIGKILL信号传播到子进程。
[program:script]
command=script
stopasgroup=true
killasgroup=true
(这些配置变量都记录在http://supervisord.org/configuration.html。)
答案 1 :(得分:2)
不确定如何使用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
在一个会话中,我有一个带有pid 27325的脚本test.sh
,而另一个会话我正在运行命令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
答案 2 :(得分:0)
另一种解决方案是捕获SIGTERM并杀死陷阱代码中的所有子项。
唯一的问题是,只有在当前运行的命令完成后,shell才会为接收到的信号运行陷阱代码 - 所以在你的情况下,仅此一点就无济于事。
但是,如果shell处于“等待”状态,陷阱将以“异步”的方式运行。
#!/usr/bin/env bash
trap 'kill 0' TERM
( cmd1 | cmd2 | cmd3 ) & wait
kill 0
将SIGTERM发送给当前进程组中的所有进程。
注意:我在这里谈论Bash。