【问题标题】:Why doesn't "trap EXIT" work in background jobs in Bash?为什么“trap EXIT”在 Bash 的后台作业中不起作用?
【发布时间】:2020-03-30 16:43:32
【问题描述】:

我正在尝试创建一个脚本,该脚本在后台启动一堆作业,然后等待它们全部运行完成。

#!/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&

为确保此脚本将等待其所有子进程,即使在生成它们时出现问题,我在最后使用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

$

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

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

【问题讨论】:

    标签: bash shell


    【解决方案1】:

    只需在run末尾调用exit即可:

    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
    }
    

    【讨论】:

    • 在运行结束时调用 exit 为什么?你有什么解释为什么在 bash 中需要它而在其他 shell 中不需要?
    • @oguzismail 相信 OP 确实问过如何在此处触发清理:“有什么办法可以解决吗?”
    • 好的。顺便说一句,这可能是一个错误,请考虑报告它。如果您设置 RETURN 陷阱而不是 EXIT,则无需显式退出即可工作。
    • 同意@oguzismail;我在文档中看不到任何暗示以这种方式创建的子外壳应该有任何独特之处。
    • 将此标记为已解决,确实是一个错误:savannah.gnu.org/support/?109840
    猜你喜欢
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多