问题
Running the following code:
#!/bin/bash
set -o pipefail
set -o errtrace
set -o nounset
set -o errexit
function err_handler ()
{
local error_code="$?"
echo "TRAP!"
echo "error code: $error_code"
exit
}
trap err_handler ERR
echo "wrong command in if statement"
if xsxsxsxs
then
echo "if result is true"
else
echo "if result is false"
fi
echo -e "\nwrong command directly"
xsxsxsxs
exit
produces the following output:
wrong command in if statement
trap.sh: line 21: xsxsxsxs: command not found
if result is false
wrong command directly
trap.sh: line 29: xsxsxsxs: command not found
TRAP!
error code: 127
How can I trap the 'command not found' error inside the if statement too?
回答1:
You can't trap ERR for the test in the if
From bash man:
The ERR trap is not executed if the failed command
is part of the command list immediately following a while or
until keyword, part of the test in an if statement, part of a
command executed in a && or || list, or if the command's return
value is being inverted via !
But you could change this
if xsxsxsxs
then ..
to this
xsxsxsxs
if [[ $? -eq 0 ]]
then ..
回答2:
Unluckly, German Garcia is right, so I wrote a workaround.
Any suggestion or improvement is more than welcome thanks.
Here's what I did so far:
#!/bin/bash
set -o pipefail
set -o errtrace
set -o nounset
set -o errexit
declare stderr_log="/dev/shm/stderr.log"
exec 2>"${stderr_log}"
function err_handler ()
{
local error_code=${1:-$?}
echo "TRAP! ${error_code}"
echo "exit status: $error_code"
stderr=$( tail -n 1 "$stderr_log" )
echo "error message: $stderr"
echo "" > "${stderr_log}"
echo "Normally I would exit now but I carry on the demo instead"
# uncomemment the following two lines to exit now.
# rm "${stderr_log}"
# exit "${error_code}"
}
trap err_handler ERR
function check ()
{
local params=( "$@" )
local result=0
local statement=''
for param in "${params[@]}"
do
local regex='\s+'
if [[ ${param} =~ ${regex} ]]
then
param=$( echo "${param}" | sed 's/"/\\"/g' )
param="\"$param\""
fi
statement="${statement} $param"
done
eval "if $statement; then result=1; fi"
stderr=$( tail -n 1 "$stderr_log" )
($statement); local error_code="$?"
test -n "$stderr" && err_handler "${error_code}"
test $result = 1 && [[ $( echo "1" ) ]] || [[ $( echo "" ) ]]
}
echo -e "\n1) wrong command in if statement"
if check xsxsxs -d "/etc"
then
echo "if returns true"
else
echo "if returns false"
fi
echo -e "\n2) right command in if statement"
if check test -d "/etc"
then
echo "if returns true"
else
echo "if returns false"
fi
echo -e "\n3) wrong command directly"
xsxsxsxs
exit
Running the above will produce:
1) wrong command in if statement
TRAP!
error code found: 0
error message: trap.sh: line 52: xsxsxs: command not found
I would exit now but I carry on instead
if returns false
2) right command in if statement
if returns true
3) wrong command directly
TRAP!
error code found: 127
error message: trap.sh: line 77: xsxsxsxs: command not found
I would exit now but I carry on instead
So the idea is basically to create a method called 'check', then to add it before the command to debug in the if statement.
I cannot catch the error code in this way, but it doesn't matter too much as long as I can get a message.
It would be nice to hear from you about that. Thanks
来源:https://stackoverflow.com/questions/13103701/how-to-trap-errors-inside-the-if-statement