在 Bash 中使用“set -e”时如何捕获 ERR
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/35800082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to trap ERR when using 'set -e' in Bash
提问by irritable_phd_syndrom
I have a simple script :
我有一个简单的脚本:
#!/bin/bash
set -e
trap "echo BOO!" ERR
function func(){
ls /root/
}
func
I would like to trap ERR if my script fails (as it will here b/c I do not have the permissions to look into /root). However, when using set -e
it is not trapped. Without set -e
ERR is trapped.
如果我的脚本失败,我想捕获 ERR(因为它在这里 b/c 我没有查看 /root 的权限)。但是,使用set -e
时不会被困。没有set -e
ERR 被困。
According to the bash man page, for set -e
:
根据 bash 手册页,对于set -e
:
... A trap on ERR, if set, is executed before the shell exits. ...
... ERR 上的陷阱(如果设置)在 shell 退出之前执行。...
Why isn't my trap executed? From the man page it seems like it should.
为什么我的陷阱没有被执行?从手册页看来应该如此。
回答by mklement0
chepner's answeris the best solution: If you want to combine set -e
(same as: set -o errexit
) with an ERR
trap, also use set -o errtrace
(same as: set -E
).
chepner 的答案是最好的解决方案:如果您想将set -e
(same as: set -o errexit
) 与ERR
陷阱结合使用,也可以使用set -o errtrace
(same as: set -E
)。
In short: use set -eE
in lieu of just set -e
:
简而言之:set -eE
代替 just 使用set -e
:
#!/bin/bash
set -eE # same as: `set -o errexit -o errtrace`
trap 'echo BOO!' ERR
function func(){
ls /root/
}
# Thanks to -E / -o errtrace, this still triggers the trap,
# even though the failure occurs *inside the function*.
func
man bash
says about set -o errtrace
/ set -E
:
man bash
说set -o errtrace
/ set -E
:
If set, any trap on ERR is inherited by shell functions, command substitutions, and commands executed in a subshell environment. The ERR trap is normally not inherited in such cases.
如果设置,则 ERR 上的任何陷阱都由 shell 函数、命令替换和在子 shell 环境中执行的命令继承。在这种情况下,ERR 陷阱通常不会被继承。
What I believe is happening:
我相信正在发生的事情:
Without
-e
: Thels
command fails inside your function, and, due to being the last command in the function, the function reportsls
's nonzero exit code to the caller, your top-level script scope. In that scope, theERR
trap is in effect, and it is invoked (but note that execution will continue, unless you explicitly callexit
from the trap).With
-e
(but without-E
): Thels
command fails inside your function, and becauseset -e
is in effect, Bash instantlyexits, directly from the function scope- and since there is noERR
trap in effect there(because it wasn't inherited from the parent scope), your trap is not called.
没有
-e
:该ls
命令在您的函数内失败,并且由于是函数中的最后一个命令,该函数会将ls
的非零退出代码报告给调用者,即您的顶级脚本范围。在该范围内,ERR
陷阱生效并被调用(但请注意,执行将继续,除非您exit
从陷阱中明确调用)。随着
-e
(但没有-E
):该ls
命令失败你的函数里面,因为set -e
在实际上,猛砸立即退出,直接从功能范围-而因为没有ERR
有效的陷阱存在(因为它没有从父作用域继承) ,你的陷阱没有被调用。
While the man
page is not incorrect, I agree that this behavior is not exactly obvious - you have to infer it.
虽然man
页面没有错误,但我同意这种行为并不完全明显 - 您必须推断它。
回答by chepner
You need to use set -o errtrace
for the function to inherit the trap.
您需要使用set -o errtrace
for 函数来继承陷阱。
回答by Ritesh
Replace ERR
with EXIT
and it will work.
替换ERR
为EXIT
,它将起作用。
The syntax of the trap
command is: trap [COMMANDS] [SIGNALS]
trap
命令的语法是:trap [COMMANDS] [SIGNALS]
For more info, please read http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html
有关更多信息,请阅读http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html