pipefail – testing pipeline exit codes

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.