我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
我正在寻找一种方法来清理混乱时,我的顶级脚本退出。
特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。
当前回答
更新:https://stackoverflow.com/a/53714583/302079通过添加退出状态和清除功能改进了这一点。
trap "exit" INT TERM
trap "kill 0" EXIT
为什么转换INT和TERM退出?因为两者都应该在不进入无限循环的情况下触发kill 0。
为什么在EXIT时触发kill 0 ?因为正常的脚本退出也应该触发kill 0。
为什么要杀死0?因为嵌套的子shell也需要被杀死。这会把整个过程树都画下来。
其他回答
这对我来说是可行的(多亏了评论的改进):
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
kill——-$$向整个进程组发送一个SIGTERM,因此也杀死后代。 在使用set -e时,指定信号EXIT很有用(更多细节请点击这里)。
通用解决方案,也在sh中工作(工作不输出任何东西到stdout):
trap "pkill -P $$" EXIT INT
脚本的加载。运行一个killall(或操作系统上可用的任何命令)命令,该命令在脚本完成后立即执行。
为了安全起见,我发现最好定义一个清理函数并从trap中调用它:
cleanup() {
local pids=$(jobs -pr)
[ -n "$pids" ] && kill $pids
}
trap "cleanup" INT QUIT TERM EXIT [...]
或完全避免该函数:
trap '[ -n "$(jobs -pr)" ] && kill $(jobs -pr)' INT QUIT TERM EXIT [...]
为什么?因为通过简单地使用陷阱'kill $(jobs -pr)'[…]当陷阱条件发出信号时,就会有后台作业在运行。当没有工作时,会看到以下(或类似的)消息:
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
因为jobs -pr是空的——我在那个“陷阱”中结束了(双关语)。
另一种选择是让脚本将自己设置为进程组的领导者,并在退出时在进程组上捕获killpg。