问题
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.
According to the bash man page, for set -e
:
... A trap on ERR, if set, is executed before the shell exits. ...
Why isn't my trap executed? From the man page it seems like it should.
回答1:
chepner's answer is 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
).
In short: use set -eE
in lieu of 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
:
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.
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 instantly exits, 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.
While the man
page is not incorrect, I agree that this behavior is not exactly obvious - you have to infer it.
回答2:
You need to use set -o errtrace
for the function to inherit the trap.
回答3:
Replace ERR
with EXIT
and it will work.
The syntax of the trap
command is: trap [COMMANDS] [SIGNALS]
For more info, please read http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_12_02.html
来源:https://stackoverflow.com/questions/35800082/how-to-trap-err-when-using-set-e-in-bash