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

特别是如果我想使用set -e,我希望后台进程在脚本退出时结束。


当前回答

为了清理一些混乱,陷阱可以使用。它可以提供特定信号到达时执行的内容列表:

trap "echo hello" SIGINT

但如果shell退出,也可以用来执行一些东西:

trap "killall background" EXIT

它是内置的,所以帮助陷阱会给你信息(适用于bash)。如果你只想消灭后台工作,你可以做到

trap 'kill $(jobs -p)' EXIT

注意使用单个',以防止shell立即替换$()。

其他回答

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

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

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

脚本的加载。运行一个killall(或操作系统上可用的任何命令)命令,该命令在脚本完成后立即执行。

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,但增加了退出代码

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

trap "pkill -P $$" EXIT INT

如果在子shell中调用Jobs -p,则不能在所有shell中工作,除非它的输出被重定向到文件而不是管道中。(我想它最初只是用于交互使用的。)

下面这些怎么样:

trap 'while kill %% 2>/dev/null; do jobs > /dev/null; done' INT TERM EXIT [...]

Debian的dash shell需要调用“jobs”,如果缺少当前作业(“%%”),则该shell无法更新。