I come across set -e
a some time ago and I admit I love it. Now, after some time I'm back to write some bash scripting.
My question is if there are some best practices when to use set -e
and when not to use it (.e.g. in small/big scripts etc.) or should I rather use a pattern like cmd || exit 1
to track errors?
“Set” can be used for deciding on something, most typically a date – when two people plan to get married, they would set a date for the wedding. They'd decide that the wedding will be on July 10th, for example. Sometimes “set” is also used for deciding on a rate or a price.
Set allows you to add at most one null element only. Set interface got one default method in Java 8: spliterator. Unlike List and arrays, Set does NOT support indexes or positions of it's elements. Set supports Generics and we should use it whenever possible.
Set in Java is an interface declared in java. util package. It extends the collection interface that allows creating an unordered collection or list, where duplicate values are not allowed. As the name implies, a set in Java is used to create a mathematical set.
List is a type of ordered collection that maintains the elements in insertion order while Set is a type of unordered collection so elements are not maintained any order. List allows duplicates while Set doesn't allow duplicate elements .
Yes, you should always use it. People make fun of Visual Basic all the time, saying it's not a real programming language, partly because of its “On Error Resume Next” statement. Yet that is the default in shell! set -e
should have been the default. The potential for disaster is just too high.
In places where it's ok for a command to fail, you can use || true
or its shortened form ||:
, e.g.
grep Warning build.log ||:
In fact you should go a step further, and have
set -eu set -o pipefail
at the top of every bash
script.
-u
makes it an error to reference a non-existent environment variable such as ${HSOTNAME}
, at the cost of requiring some gymnastics with checking ${#}
before you reference ${1}
, ${2}
, and so on.
pipefail
makes things like misspeled-command | sed -e 's/^WARNING: //'
raise errors.
If your script code checks for errors carefully and properly where necessary, and handles them in an appropriate manner, then you probably don't ever need or want to use set -e
.
On the other hand if your script is a simple sequential list of commands to be run one after another, and if you want the script to terminate if any one of those fail, then sticking set -e
at the top would be exactly what you would want to do to keep your script simple and uncluttered. A perfect example of this would be if you're creating a script to compile a set of sources and you want the compile to stop after the first file with errors is encountered.
More complex scripts can combine these methods since you can use set +e
to turn its effect back off again and go back to explicit error checking.
Note that although set -e
is supposed to cause the shell to exit IFF any untested command fails, it is wise to turn it off again when your code is doing its own error handling as there can easily be weird cases where a command will return a non-zero exit status that you're not expecting, and possibly even such cases that you might not catch in testing, and where sudden fatal termination of your script would leave something in a bad state. So, don't use set -e
, or leave it turned on after using it briefly, unless you really know that you want it.
Note also that you can still define an error handler with trap ERR
to do something on an error condition when set -e
is in effect, as that will still be run before the shell exits.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With