Bash functions ignore set -e
I ended up wrapping the code to do so in a utility function below.
#!/bin/bash -e
# Runs given code aborting on first error and taking desired action on failure
# $1 code to invoke, can be expression or function name
# $2 error handling code, can be function name or expressions
function saferun {
set +e
(set -E ; trap 'exit 1' ERR ; eval $1)
[ $? -ne 0 ] && eval $2
set -e
}
function foo() {
echo Entering foo
false
echo Should not reach this line
}
saferun foo "echo I want to see this line on failure in foo"
foo
Let's break it down:
set +e
andset -e
are used to suppress failure on error, as otherwise the script will just exit on first errortrap
is used to abort the execution on any error (instead ofset -e
)()
is used to run the given code in subshell, so outer script will keep running after failure, andset -E
is used to pass the trap into the subshell. so(set -E ; trap 'exit 1' ERR ; eval $1)
run the given code / function aborting on first error while not exiting the whole script$? -ne 0
check for failures andeval $2
runs the error handling code
Bash ignoring error for a particular command
The solution:
particular_script || true
Example:
$ cat /tmp/1.sh
particular_script()
{
false
}
set -e
echo one
particular_script || true
echo two
particular_script
echo three
$ bash /tmp/1.sh
one
two
three
will be never printed.
Also, I want to add that when pipefail
is on,
it is enough for shell to think that the entire pipe has non-zero exit code
when one of commands in the pipe has non-zero exit code (with pipefail
off it must the last one).
$ set -o pipefail
$ false | true ; echo $?
1
$ set +o pipefail
$ false | true ; echo $?
0
With set -e, is it possible to ignore errors for certain commands?
Add || :
(or anything else that is guaranteed not to fail but that's the simplest) to the end of the command.
Though many people would simply tell you that set -e
isn't worth it because it isn't as useful as you might think (and causes issues like this) and manual error checking is a better policy.
(I'm not in that camp yet though the more I run into issues like this the more I think I might get there one day.)
From thatotherguy's comment explaining one of major the issues with set -e
:
The problem with
set -e
isn't that you have to be careful about which commands you want to allow to fail. The problem is that it doesn't compose. If someone else reads this post and usessource yourfile || :
to source this script while allowing failure, suddenlyyourfile
will no longer stop on errors anywhere. Not even on failing lines after an explicitset -e
.
How to disable set -e and set -o
For all options, the opposite of set -/code> is
set +/code> (note the plus sign).
So set +e
will undo set -e
, and set +o pipefail
will undo set -o pipefail
.
set -e ignored in function when invoked in context where exit status is tested?
Test 1
Use set -E
(aka set -o errtrace
) in addition to set -e
if you want the behavior of set -e
to apply even inside a function:
set -E -e
foo () (
echo $SHELLOPTS
false
echo set -e failed
)
echo test1:
foo
test $? -ne 0 && echo died
echo
echo test2:
foo && echo died
Note, however, that triggers an exit, not a return, should the function fail. Thus, the output of this is something akin to:
test1:
braceexpand:errexit:errtrace:hashall:interactive-comments:xtrace
...with no further content, as the exit occurs immediately on the false
.
Test 2
As for foo && echo died
, because the exit status for foo
is tested, the flag to disable set -e
is enabled during its execution, so it's expected, defined behavior for this flag to have no effect.
Advice
The behavior of set -e
is not intuitive. Before depending on it, be sure you fully understand all the examples of behavior given in BashFAQ #105, and consider also reading through the excellent fvue writeup of error handling in bash.
What does set -e mean in a bash script?
From help set
:
-e Exit immediately if a command exits with a non-zero status.
But it's considered bad practice by some (bash FAQ and irc freenode #bash FAQ authors). It's recommended to use:
trap 'do_something' ERR
to run do_something
function when errors occur.
See http://mywiki.wooledge.org/BashFAQ/105
Can “set -e” be disabled in a script?
@Charles Duffy on another thread answered this. not exit a bash script when one of the sub-script fails
set +e undoes set -e. However, using set -e is a bad idea in general; better to use || exit on individual commands where you want a nonzero exit status to be fatal. (Skip past the parable to the exercises if you're in a hurry). – Charles Duffy
Related Topics
How to Get Wget Only Save File If Its Complete
Linux Mail Adding Content Type Headers Not Working
How to Quickly Check If Linux 'Unzip' Is Installed Using Perl
How to Avoid Sigchld Error in Bash Script That Uses Gnu Parallel
"Relocation R_X86_64_32S Against '.Bss' Can Not Be Used When Making a Shared Object"
How to Display Nc Return Value in Linux Shell Script
When Is The System Call Set_Tid_Address Used
How to Use Qemu for Learning Arm Linux Kernel Development
How to Install Pysqlite for Python3.4.2
Is There a Linker Flag to Force It to Load All Shared Libraries at Start Time
Prevent Git Checkout from Overwriting a File
How Does Ltrace() Display Rand()
Linux - Limit Usb Device Bandwidth
Number of Subdirectories in a Directory
How to Rename a Kernel Module Name Without Renaming The .Ko Passed to Insmod
How to Test Your Own Linux Module
How to Sort The String Array in Linux Bash Shell
How to View Function Names and Parameters Contained in an Elf File