出于测试目的,我有这个 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 应用程序启动 - 脚本退出时需要某种形式的清理 - 我应该研究的任何选项或重写脚本以在退出时清理自身的任何方式?
我会做这样的事情:
#!/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
等待完成,wait
将返回该进程的退出状态。
最后,如果 wait
返回错误状态,我们要kill
子进程。幸运的是我们保存了它的 PID。这种方法的优点是您可以记录一些错误消息或以其他方式识别导致脚本退出的信号。
正如其他人所提到的,如果您不关心在 post-导出。
要使 trap
以您想要的方式工作,您需要将其与 wait
配对 - bash
手册页说“如果bash
正在等待命令完成并接收到已为其设置了 trap
的信号,trap
将不会执行,直到命令完成。” wait
是解决这个问题的方法。
如果需要,您也可以将其扩展到更多子进程。我并没有真正详尽地测试这个,但它似乎在这里工作。
$ ./test-k.sh &
[1] 12810
12810
$ kill 12810
$ ps -ef | grep find
$