#!/bin/bash -e
The
-e
option will cause the script to exit immediate if a command has exited with a non-zero status. This way your script will fail as early as possible, and you never get into a case where on the surface, it looks like the script completed, but you're left with an empty file, or missing lines, etc.Of course, this is only for "simple" commands, so in practice, you can think of it terminating immediately if the entire line fails. So a script like:
will still print "i am still running," and the script will exit with a zero exit status.
#!/usr/bin/bash -e
/usr/bin/false || true
echo "i am still running"
Of course, if you wrote it that way, that's probably what you're expecting. And, it's easy enough to change (just change "||" to "&&").
The thing that was slightly surprising to me was how a script would behave using pipes.
If your script is piping its output to another command, it turns out that the return status of a pipeline is the exit status of its last command. So, the script above will also print "i am still running" and exit with a 0 exit status.
#!/bin/bash -e
/usr/bin/false | sort > sorted.txt
echo "i am still running"
Bash provides a
PIPESTATUS
variable, which is an array containing a list of the exit status values from the pipeline. So, if we checked ${PIPESTATUS[0]}
it would contain 1 (the exit value of /usr/bin/false
), and ${PIPESTATUS[1]}
would contain 0 (exit value of sort). Of course, PIPESTATUS
is volatile, so, you must check it immediately. Any other command you run will affect its value.This is great, but not exactly what I wanted. Luckily, there's another bash option
-o pipefail
, which will change the way the pipeline exit code is derived. Instead of being the last command, it will become the last command with a non-zero exit status. SoSo, thanks to pipefail, the above script will work as we expect. Since
#!/bin/bash -e -o pipefail
/usr/bin/false | sort > sorted.txt
echo "this line will never execute"
/usr/bin/false
returns a non-zero exit status, the entire pipeline will return a non-zero exit status, the script will die immediately because of -e
, and the echo will never execute.Of course, all of this information is contained in the bash man page, but I had never really ran into it / looked into it before, and I thought it was interesting enough to write up.
No comments:
Post a Comment