bash – PIPESTATUS and pipefail

  • by

Evaluate the exit code of an executed command is a normal practice in shell scripts, but what happens if you also want that command to pipe in another command? You lose your precious exit code.

Bash provides you with the variable array PIPESTATUS, containing the exit codes along all the pipeline.

# false | tee -a mylogfile
# echo $?
0
# false | tee -a mylogfile
# echo ${PIPESTATUS[0]}
1
# echo foo | false | true
# echo ${PIPESTATUS[1]}
1

But sometimes you want to execute commands inside a subshell, typically for gathering the output, in this case it’s not possible to get the PIPESTATUS variable, since a subshell is a new spawned process, so it inherits the environment from the parent but variables modified inside it will die with it. Still, the process exit code is retrievable, the problem is the exit code of the process by default is the exit code of the last executed command.

Bash, as usual, is your friend, and gives you the “pipefail” option with the “set” builtin command.

If “pipefail” is set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default. (complete list of options here: https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html#The-Set-Builtin )

# myvar=$( false | true )
# echo $?
0
# set -o pipefail
# myvar=$( false | true )
# echo $?
1
# set +o pipefail
Tags:

Leave a Reply

Your email address will not be published.