The exit status of a pipe is the exit status of the right-hand command. The exit status of the left-hand command is ignored.
(Note that which lss | echo $?
doesn't show this. You would run which lss | true; echo $?
to show this. In which lss | echo $?
, echo $?
reports the status of the last command before this pipeline.)
The reason shells behave this way is that there is a fairly common scenario where an error in the left-hand side should be ignored. If the right-hand side exits (or more generally closes its standard input) while the left-hand side is still writing, then the left-hand side receives a SIGPIPE signal. In this case, there is usually nothing wrong: the right-hand side doesn't care about the data; if the role of the left-hand side is solely to produce this data then it's ok for it to stop.
However, if the left-hand side dies for some reason other than SIGPIPE, or if the job of the left-hand side was not solely to produce data on standard output, then an error in the left-hand side is a genuine error that should be reported.
In plain sh, the only solution is to use a named pipe.
set -e
mkfifo p
command1 >p & pid1=$!
command2 <p
wait $pid1
In ksh, bash and zsh, you can instruct the shell to make a pipeline exit with a nonzero status if any component of the pipeline exits with a nonzero status. You need to set the pipefail
option:
- ksh:
set -o pipefail
- bash:
shopt -s pipefail
- zsh:
setopt pipefail
(or setopt pipe_fail
)
In mksh, bash and zsh, you can get the status of every component of the pipeline using the variable PIPESTATUS
(bash, mksh) or pipestatus
(zsh), which is an array containing the status of all the commands in the last pipeline (a generalization of $?
).
which lss | echo $?
, theecho
is started beforewhich
has exited; the shell generating the command line forecho
has no possible way of knowing what the exit status ofwhich
will later be. – Charles Duffy May 20 '17 at 17:13tail -f filename | echo $?
. The shell has to replace the$?
variable before waiting for thetail
command to finish. – Barmar May 24 '17 at 19:02