The problem
In bash
, running test programs which indicate their pass or fail status via an exit code can be problematic when they are run as part of a pipeline in Linux, Mac OS X or Cygwin since the reported exit code of a pipeline is normally the exit code of the last program in the pipeline. If the test program is not the last program in the pipeline, then its exit code will be hidden by the exit code of the last program.
The solution
bash
version 3 introduced an option which changes the exit code behavior of pipelines and reports the exit code of the pipeline as the exit code of the last program to return a non-zero exit code. So long as none of the programs following the test program report a non-zero exit code, the pipeline will report its exit code to be that of the test program. To enable this option, simply execute:
set -o pipefail
in the shell where the test program will execute.
Caveat Emptor
The pipefail
option was introduced in bash
version 3 which is supported in current Linux, Mac OS X, Cygwin releases of bash
but is not supported by the default bash shipped on Mac OS X 10.4 and earlier..
To work around this lagging version on Mac OS X 10.4, you can simply download, build and install the latest version of bash
from http://ftp.gnu.org/gnu/bash/ into your /usr/local/bin
directory. Then code your shell scripts to use the shebang !#/usr/local/bin/bash
instead of the normal /bin/bash
. For systems such as Linux or Cygwin which already provide a pipefail
capable version of bash
, simply create a hard link from /usr/local/bin/bash
to the system version /bin/bash.
ln /bin/bash /usr/local/bin/bash
Updated April 20, 2011 to show Mac OS X 10.5 and later support pipefail. Hat tip to Ben Denckla for the updated Mac OS X support.