May 05 2008
BASH Pipeline Exit Codes
I think I’ve mentioned many times on this blog, but one of the most satisfying things regarding Linux and Unix are that you’re never done learning about it. A never-ending lesson in operating systems! Well, chalk up another lightbulb moment for me this morning.
Imagine a script wherein a process needs to be checked for proper exit. Let’s say “mysqldump”. Typically I’d do something like this, for example:
#!/bin/bash
STATUS=1
while [ ${STATUS} -ne 0 ]
do
mysqldump -uroot -psomepass –all-databases > sql-backup.sql
STATUS=${?}
done
exit 0
That’ll work just fine–the special reserved variable ${?} contains the exit code of the last run command. Mysqldump is kind enough to use non-zero ones on any kind of error, so if it doesn’t work in our script we’ll retry.
But for instance, let’s say our script looks like this:
#!/bin/bash
STATUS=1
while [ ${STATUS} -ne 0 ]
do
mysqldump -uroot -psomepass –all-databases | gzip > sql-backup.sql
STATUS=${?}
done
exit 0
The problem here is that ${?} now contains the exit code for gzip, not mysqldump! Will gzip respond properly if mysqldump doesn’t provide an input stream from the pipe? Maybe, maybe not. Bottom line is that it isn’t reliable, and not what I’d consider good shell programming.
Instead, check out this solution:
#!/bin/bash
STATUS=1
while [ ${STATUS} -ne 0 ]
do
mysqldump -uroot -psomepass –all-databases | gzip > sql-backup.sql
STATUS=${PIPESTATUS[0]}
done
exit 0
The BASH reserved array ${PIPESTAUTUS[x]} contains the exit codes for all programs in the array. In this example, ${PIPESTATUS[0]} is mysqldump, and ${PIPESTATUS[1]} is gzip.
This makes sense. What I am puzzling over at the moment is how to terminate
the flow in a pipeline if say the first command in the pipeline fails. I want it to terminate, and the script to exit. Any thoughts?
Len, you might want to try using “set -e” in your script. It will terminate the shell if any command exits with non-zero.
You might also want to try something like:
cmd1 || exit 1 | cmd2
I haven’t tested it, that’s just off the top of my head.