mus*_*hil 80 shell bash signals trap
对于许多例子trap
使用trap ... INT TERM EXIT
的清理任务。但是真的有必要列出所有三个 sigspecs 吗?
手册上说:
如果 SIGNAL_SPEC 为 EXIT (0),则在退出 shell 时执行 ARG。
我相信这适用于脚本是否正常完成或因为它收到SIGINT
或SIGTERM
. 一个实验也证实了我的信念:
$ cat ./trap-exit
#!/bin/bash
trap 'echo TRAP' EXIT
sleep 3
$ ./trap-exit & sleep 1; kill -INT %1
[1] 759
TRAP
[1]+ Interrupt ./trap-exit
$ ./trap-exit & sleep 1; kill -TERM %1
[1] 773
TRAP
[1]+ Terminated ./trap-exit
Run Code Online (Sandbox Code Playgroud)
那为什么这么多例子一一列举INT TERM EXIT
呢?或者我错过了什么,有没有鞋底EXIT
会错过的情况?
Zaz*_*Zaz 34
是,有一点不同。
当您按下Enter、 或发送SIGINT
或时,此脚本将退出SIGTERM
:
trap '' EXIT
echo ' --- press ENTER to close --- '
read response
Run Code Online (Sandbox Code Playgroud)
当您按 时,此脚本将退出Enter:
trap '' EXIT INT TERM
echo ' --- press ENTER to close --- '
read response
Run Code Online (Sandbox Code Playgroud)
* 在sh、Bash和Zsh 中测试。(当你添加一个命令让陷阱运行时不再在sh 中工作)
还有@Shawn 所说的:Ash和Dash不会用EXIT
.
因此,要稳健地处理信号,最好EXIT
完全避免捕获,并使用以下内容:
cleanup() {
echo "Cleaning stuff up..."
exit
}
trap cleanup INT TERM
echo ' --- press ENTER to close --- '
read var
cleanup
Run Code Online (Sandbox Code Playgroud)
Sha*_*off 26
该POSIX规范并没有太多说的,导致执行EXIT陷阱,只有它的环境必须考虑什么是执行时它像的条件。
在 Busybox 的 ash shell 中,由于 SIGINT 或 SIGTERM,您的陷阱退出测试在退出之前不会回显“TRAP”。我怀疑还有其他 shell 可能也不能那样工作。
# /tmp/test.sh & sleep 1; kill -INT %1
#
[1]+ Interrupt /tmp/test.sh
#
#
# /tmp/test.sh & sleep 1; kill -TERM %1
#
[1]+ Terminated /tmp/test.sh
#
Run Code Online (Sandbox Code Playgroud)
ijw*_*ijw 13
完善最后一个答案,因为它有问题:
# Our general exit handler
cleanup() {
err=$?
echo "Cleaning stuff up..."
trap '' EXIT INT TERM
exit $err
}
sig_cleanup() {
trap '' EXIT # some shells will call EXIT after the INT handler
false # sets $?
cleanup
}
trap cleanup EXIT
trap sig_cleanup INT QUIT TERM
Run Code Online (Sandbox Code Playgroud)
以上几点:
当我测试时,INT 和 TERM 处理程序不会为我退出 - 它们处理错误然后外壳返回退出(这并不奇怪)。所以我确保清理之后退出,并且在信号的情况下总是使用错误代码(在正常退出的另一种情况下,保留错误代码)。
使用 bash,似乎在 INT 处理程序中退出也会调用 EXIT 处理程序,因此我解开退出处理程序并自己调用它(无论行为如何,它都可以在任何 shell 中工作)。
我捕获退出是因为 shell 脚本可以在到达底部之前退出 - 语法错误,设置 -e 和非零返回,只需调用 exit。你不能依靠 shellscript 深入了解。
SIGQUIT 是 Ctrl-\ 如果您从未尝试过。为您提供额外的核心转储。所以我认为它也值得陷害,即使它有点晦涩。
过去的经验表明,如果您(像我一样)总是多次按下 Ctrl-C,您有时会在 shell 脚本的清理部分中途遇到它,因此这有效,但并不总是如您所愿。
小智 8
这就是如何使 Bash 脚本报告其返回代码$?
,同时能够捕获 SIGINT 和 SIGTERM 信号。我发现这对于在 CI/CD 管道中运行的脚本非常有用:
notify() {\n [[ $1 = 0 ]] || echo \xe2\x9d\x8c EXIT $1\n # you can notify some external services here,\n # ie. Slack webhook, Github commit/PR etc.\n}\n\ntrap '(exit 130)' INT\ntrap '(exit 143)' TERM\ntrap 'rc=$?; notify $rc; exit $rc' EXIT\n
Run Code Online (Sandbox Code Playgroud)\n
归档时间: |
|
查看次数: |
68272 次 |
最近记录: |