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.
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.
command1 >p & 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
set -o pipefail
shopt -s pipefail
setopt pipefail (or
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