我用以下代码捕获 INT 和 ERR
set -ex -o pipefail
dest=$(mktemp -d)
cd "$dest"
trap "echo; echo Clean up; rm -rf $dest" INT ERR
sleep 9999
Run Code Online (Sandbox Code Playgroud)
当我按下^C
清理回调被执行多次
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
++ echo
++ echo Clean up
Clean up
++ rm -rf /tmp/tmp.KYXL110516
Run Code Online (Sandbox Code Playgroud)
这是预期的行为吗?是否可以只执行一次?
您同时收到 INT 和 ERR 信号;SIGINT 被交给sleep
,他以非零返回码退出。然后非零返回码触发 SIGERR 陷阱。
如果 sigspec 为 ERR,则只要管道(可能由单个简单命令组成)、列表或复合命令返回非零退出状态,就会执行命令 arg...
一个例子,查看单独的陷阱:
set -ex -o pipefail
trap "echo Clean up for INT" INT
trap "echo Clean up for ERR" ERR
sleep 9999
Run Code Online (Sandbox Code Playgroud)
执行,然后 Control-C:
+ trap 'echo Clean up for INT' INT
+ trap 'echo Clean up for ERR' ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ echo Clean up for ERR
Clean up for ERR
Run Code Online (Sandbox Code Playgroud)
至于只调用一次陷阱,一种选择是在ERR
陷阱内重置INT
陷阱:
...
trap "echo Clean up for INT; trap ERR" INT ERR
...
Run Code Online (Sandbox Code Playgroud)
...这导致:
+ trap 'echo Clean up for INT; trap ERR' INT ERR
+ sleep 9999
^C++ echo Clean up for INT
Clean up for INT
++ trap ERR
Run Code Online (Sandbox Code Playgroud)