为什么“trap EXIT”在 Bash 的后台作业中不起作用?

ea7*_*abe 3 bash shell

我正在尝试创建一个脚本,在后台启动一堆作业,然后等待所有作业运行完成。

#!/bin/sh

cleanup() {
    wait
    echo cleanup
}

do_work() {
    sleep 2
    echo done "$@"
}

run() {
    trap cleanup EXIT
    do_work 1 &
    # ... some code that may fail ...
    do_work 2 &
    # I can't just call cleanup() here because of possible early exit
}

# The script itself runs in the background too.
run&
Run Code Online (Sandbox Code Playgroud)

为了确保该脚本将等待其所有子进程,即使在生成子进程时出现问题,我也会使用而trap cleanup EXIT不是仅cleanup在最后使用。

但是当我在不同的 shell 中运行此脚本时,我得到以下结果:

$ for sh in zsh dash 'busybox ash' bash; do echo "$sh:"; $sh script.sh; sleep 3; echo; done
zsh:
done 1
done 2
cleanup

dash:
done 1
done 2
cleanup

busybox ash:
done 2
done 1
cleanup

bash:
done 2
done 1

$
Run Code Online (Sandbox Code Playgroud)

在 Bash 中,trap 命令似乎被完全忽略。原因可能是什么?有办法解决吗?

man bash-builtins说了一些关于进入外壳时被忽略的信号无法被捕获的信息,但我不知道这如何适用于这种情况......

rtx*_*x13 5

exit只需在末尾调用run

run() {
    trap cleanup EXIT
    do_work 1 &
    # ... some code that may fail ...
    do_work 2 &
    # I can't just call cleanup() here because of possible early exit
    exit
}
Run Code Online (Sandbox Code Playgroud)

  • 将其标记为已解决,这确实是一个错误:https://savannah.gnu.org/support/?109840 (2认同)