Is there a way to have a function in my bash script auto run on any command error?
You can use bash trap ERR to make your script quit if any command returns status greater than zero and execute your function on exiting.
Something like:
myfunc() {
echo 'Error raised. Exiting!'
}
trap 'myfunc' ERR
# file does not exist, causing error
ls asd
echo 123
Note that bash trap ERR
does implicit set -o errexit
or set -e
and is not POSIX.
And the ERR
trap is not executed if the failed command is part of the command list immediately following until
or while
keyword, part of the test following the if
or elif
reserved words, part of a command executed in &&
or ||
list, or if the command’s return status is being inverted using !
.
A (perhaps) simpler variation on the accepted answer:
- Use
set -e
to cause the failure of one command to abort the execution of a list. - Simply list your commands.
- Use an
if
-then
-else
statement to execute your error-handling command(s). This last piece is a bit tricky. Watch:
set -e if cmd1 # e.g., cd foo cmd2 # e.g., rm a cmd3 # e.g., cd bar cmd4 # e.g., rm b then set +e commands to do upon success (if any) else set +e myfunc other commands to do upon failure (if any) fi
The tricky part is that you put your commands
into the if
part of the if
-then
-else
,
not the then
part or the else
part.
Recall that the syntax of the if
statement is
if list; then list; [ elif list; then list; ] ... [ else list; ] fi ↑↑↑↑The
set -e
tells the shell that,
if cmd1
(cd foo
) fails,
it should not go on and execute cmd2
(rm a
),
and so on down the line.
If this happened to a command at the outermost level of a shell script,
the shell would exit.
However, since the cmd1
· cmd2
· cmd3
· cmd4
is a (compound) list following an if
,
the failure of any of those four commands
simply causes the entire list to fail —
which causes the else
clause to be executed.
If all four commands succeed, the then
clause is executed.
In either case, the first thing you should do is probably to disable
(turn off) the e
option by doing set +e
.
Otherwise, the script might get blown out of the water
if a command in myfunc
fails.
set -e
is specified and described in the POSIX specification.