我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
当前回答
一个可以在Linux、BSD和MacOS x下工作的不错的版本。首先尝试发送SIGTERM,如果不成功,10秒后终止进程。
KillJobs() {
for job in $(jobs -p); do
kill -s SIGTERM $job > /dev/null 2>&1 || (sleep 10 && kill -9 $job > /dev/null 2>&1 &)
done
}
TrapQuit() {
# Whatever you need to clean here
KillJobs
}
trap TrapQuit EXIT
请注意,作业不包括子代进程。
其他回答
另一种选择是让脚本将自己设置为进程组的领导者,并在退出时在进程组上捕获killpg。
脚本的加载。运行一个killall(或操作系统上可用的任何命令)命令,该命令在脚本完成后立即执行。
通用解决方案,也在sh中工作(工作不输出任何东西到stdout):
trap "pkill -P $$" EXIT INT
只是为了多样性,我将发布https://stackoverflow.com/a/2173421/102484的变体,因为这个解决方案在我的环境中会导致消息“终止”:
trap 'test -z "$intrap" && export intrap=1 && kill -- -$$' SIGINT SIGTERM EXIT
如果在子shell中调用Jobs -p,则不能在所有shell中工作,除非它的输出被重定向到文件而不是管道中。(我想它最初只是用于交互使用的。)
下面这些怎么样:
trap 'while kill %% 2>/dev/null; do jobs > /dev/null; done' INT TERM EXIT [...]
Debian的dash shell需要调用“jobs”,如果缺少当前作业(“%%”),则该shell无法更新。