Question

Using trap may help in writing cleanest bash script. However I would like to know whether a solution exists in order to trap an error in the following case:

GNU bash, version 4.2.45

case OK

#!/bin/bash
trap 'echo OK i see error at line $LINENO;exit' ERR 
unknowncommand
echo "test KO should never reach me"

case KO

#!/bin/bash
trap 'echo OK i see error at line $LINENO;exit' ERR
unknowncommand && echo "miss the trap"
echo "test KO should never reach me"
  • Unfortunately we reach the last sentence as if && make the whole sentence not an ERR.
Was it helpful?

Solution

You want to evaluate the exit status of the whole evaluation, rather than attempting a short-circuit. One way to do this is to wrap the entire thing in a subshell. For example:

#!/bin/bash
trap 'echo "OK i see error at line $LINENO"; exit' ERR
(unknowncommand && echo "miss the trap")
echo "test KO should never reach me"

This works as expected. The result looks like this:

$ /tmp/err.sh 
/tmp/err.sh: line 3: unknowncommand: command not found
OK i see error at line 3

OTHER TIPS

According to the documentation for 4.2 (recent at the time of this answer)

If a sigspec is ERR, the command arg is executed whenever a simple command has a non-zero exit status, subject to the following conditions. The ERR trap is not executed if the failed command is part of the command list immediately following an until or while keyword, part of the test following the if or elif reserved words, part of a command executed in a && or || list, or if the command’s return status is being inverted using !.

One way to work around this is to use an if statement to check the value of $? instead of an && list.

trap 'echo OK i see error at line $LINENO;exit' ERR
unknowncommand
if [ $? -eq 0 ]; then
    echo "miss the trap"
fi
echo "test KO should never reach me"

Another that seems to work is to wrap the command in a subshell, although the documentation does not seem to mention that ERR is fired for a failed subshell. (A subshell is not generally considered a simple command, but the documentation doesn't deny it, either.) The exit status of a subshell is the exit status of the last line, which in this case (x && y) is the exit status of x if it fails, or else the exit status of y.

trap 'echo OK i see error at line $LINENO;exit' ERR
( unknowncommand && echo "miss the trap" )
echo "test KO should never reach me"
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top