出于测试目的,我有这个shell脚本
#!/bin/bash
echo $$
find / >/dev/null 2>&1
从交互式终端运行,ctrl + c将终止bash和find命令。
$ ./test-k.sh
13227
<Ctrl+C>
$ ps -ef |grep find
$
在后台运行它,并且仅杀死shell将孤立在脚本中运行的命令。
$ ./test-k.sh &
[1] 13231
13231
$ kill 13231
$ ps -ef |grep find
nos 13232 1 3 17:09 pts/5 00:00:00 find /
$
我希望这个shell脚本在退出时终止所有子进程,无论它是如何被调用的。它最终将从python和java应用程序启动 - 当脚本退出时需要进行某种形式的清理 - 我应该查看的任何选项或任何重写脚本以在退出时自行清理的方法?
答案 0 :(得分:15)
我会做这样的事情:
#!/bin/bash
trap : SIGTERM SIGINT
echo $$
find / >/dev/null 2>&1 &
FIND_PID=$!
wait $FIND_PID
if [[ $? -gt 128 ]]
then
kill $FIND_PID
fi
我想有些解释是有道理的。出门,我们需要改变一些默认的信号处理。 :
是一个无操作命令,因为传递一个空字符串会导致shell忽略信号而不是对它做一些事情(与我们想做的事情相反)。
然后,find
命令在后台运行(从脚本的角度来看),我们调用wait
内置函数来完成它。由于我们向上面的trap
发出了实际命令,因此当处理信号时,wait
将以大于128的状态退出。如果完成的进程wait
完成,{{1} }将返回该进程的退出状态。
最后,如果wait
返回该错误状态,我们希望wait
子进程。幸运的是我们保存了它的PID。此方法的优点是您可以记录一些错误消息或以其他方式识别信号导致脚本退出。
正如其他人所提到的,如果您不关心在退出后留下任何信息,那么将kill
作为您kill -- -$$
的参数是另一种选择。
要让trap
以您想要的方式工作,您需要将其与trap
配对 - wait
手册页说“如果bash
正在等待命令完成并接收已设置bash
的信号,在命令完成之前不会执行trap
。“ trap
是绕过这个打嗝的方法。
如果需要,您可以将其扩展到更多子进程。我并没有详尽地测试这个,但它似乎在这里工作。
wait
答案 1 :(得分:8)
正在为这个问题寻找一个优雅的解决方案,并在其他地方找到了以下解决方案。
trap 'kill -HUP 0' EXIT
我自己的手册没有说明0
的含义,但是从挖掘中看,它似乎意味着当前的流程组。由于脚本是自己的进程组,因此最终会向所有脚本的子节点,前景和后台发送SIGHUP。
答案 2 :(得分:6)
向小组发送信号。
因此,而不是kill 13231
做:
kill -- -13231
如果你是从python开始,那么看看: http://www.pixelbeat.org/libs/subProcess.py 它展示了如何在启动时模仿shell 并杀死一个团体
答案 3 :(得分:1)
只需在脚本中添加这样的行:
trap "kill $$" SIGINT
您可能需要在设置中将“SIGINT”更改为“INT”,但这会在您按Ctrl-C时基本上终止您的进程和所有子进程。
答案 4 :(得分:1)
@Patrick的回答几乎完成了这个诀窍,但是如果当前 shell的父进程在同一个组中(它也杀死了父进程)它就不起作用)。
我发现这更好:
trap 'pkill -P $$' EXIT
有关详细信息,请参阅here。
答案 5 :(得分:0)
你需要做的是捕获kill信号,杀死find命令并退出。