我正在寻找一种方法来清理混乱时,我的顶级脚本退出。

特别是如果我想使用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也需要被杀死。这会把整个过程树都画下来。

其他回答

通用解决方案,也在sh中工作(工作不输出任何东西到stdout):

trap "pkill -P $$" EXIT INT

这对我来说是可行的(多亏了评论的改进):

trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT

kill——-$$向整个进程组发送一个SIGTERM,因此也杀死后代。 在使用set -e时,指定信号EXIT很有用(更多细节请点击这里)。

trap 'kill $(jobs -p)'退出

我只会对Johannes的答案做一些小改动,并使用jobs -pr将kill限制为正在运行的进程,并在列表中添加更多的信号:

trap 'kill $(jobs -pr)' SIGINT SIGTERM EXIT

只是为了多样性,我将发布https://stackoverflow.com/a/2173421/102484的变体,因为这个解决方案在我的环境中会导致消息“终止”:

trap 'test -z "$intrap" && export intrap=1 && kill -- -$$' SIGINT SIGTERM EXIT
function cleanup_func {
    sleep 0.5
    echo cleanup
}

trap "exit \$exit_code" INT TERM
trap "exit_code=\$?; cleanup_func; kill 0" EXIT

# exit 1
# exit 0

类似于https://stackoverflow.com/a/22644006/10082476,但增加了退出代码