我使用以下代码捕获 INT 和 ERR
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
当我按下^C
清理回调执行多次
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
这是预期的行为吗?是否可以只执行一次?
您同时收到 INT 和 ERR 信号;SIGINT 被交给
sleep
,他以非零返回码退出。非零返回码然后触发 SIGERR 的陷阱。一个例子,查看单独的陷阱:
执行,然后是 Control-C:
至于只调用一次陷阱,一种选择是在
ERR
陷阱内重置INT
陷阱:...这导致:
在
bash
中,您可以简单地将其替换为trap "my-cleanup-command" EXIT
。此陷阱将在脚本退出时运行,包括是否发送 SIGINT。在我看来,这通常是更优雅的方法......除了它是特定于 bash 的事实。POSIX 中提到了 EXIT 陷阱,但未指定行为。在许多其他 shell 中,如果 shell 由于信号而退出,则不会运行 EXIT 陷阱。
https://unix.stackexchange.com/a/57960/29483
有时我真的很讨厌 shell 脚本:)。
查看链接的答案,我认为确保在第一个陷阱之后没有代码运行的不太特定于 bash 的方法是立即退出。似乎有不同的方法可以做到这一点,但这是我会尝试的最简单的方法。