How to copy standard output and catch error code in the meantime

It is widespread to display and store command output using tee utility, but taking full advantage of it requires applying a slightly different error catching strategy.


The exit status of the whole pipeline will be determined by the exit code of the last command.

$ false | tee /tmp/temporary_logfile
$ echo $?

Solution #1

Set pipefail option, so the exit status of the whole pipeline will be defined as the value of the rightmost command that returned a non-zero exit code.

I have placed commands between parentheses to execute these in a subshell environment, so this option does not remain in effect after the subshell completes.
$ (set -o pipefail; false | tee /tmp/temporary_logfile)
$ echo $?

This solution is sufficient for simple cases where you execute a single command and copy its output to a file. I am using it most of the time.

Solution #2

This solution is suitable for advanced cases where you use multiple commands and want to verify exit status for each command in the pipeline, which is especially useful inside custom-built shell scripts.

It uses PIPESTATUS array variable that contains a list of exit status values from the processes in the most recently executed pipeline.

$ false | nonexistent | command | tee /tmp/1
$ echo ${PIPESTATUS[@]}
1 127 0 0

More detailed description.

$ false | nonexistent | command | tee /tmp/1
$ echo -e "false: ${PIPESTATUS[0]}\nnonexistent: ${PIPESTATUS[1]}\ncommand: ${PIPESTATUS[2]}\ntee /tmp/1: ${PIPESTATUS[3]}"
false: 1
nonexistent: 127
command: 0
tee /tmp/1: 0