Lo stato di uscita di una pipe è lo stato di uscita del comando di destra. Lo stato di uscita del comando a sinistra viene ignorato.
(Notare che which lss | echo $?
non lo mostra. Si eseguirà which lss | true; echo $?
per mostrarlo. In which lss | echo $?
, echo $?
riporta lo stato dell'ultimo comando prima di questa pipeline.)
Il motivo per cui le shell si comportano in questo modo è che esiste uno scenario abbastanza comune in cui un errore nella parte sinistra dovrebbe essere ignorato. Se il lato destro esce (o più generalmente chiude il suo input standard) mentre il lato sinistro sta ancora scrivendo, il lato sinistro riceve un segnale SIGPIPE. In questo caso, di solito non c'è nulla di sbagliato: il lato destro non si preoccupa dei dati; se il ruolo del lato sinistro è solo quello di produrre questi dati, allora è giusto che si fermi.
Tuttavia, se il lato sinistro muore per qualche motivo diverso da SIGPIPE, o se il compito del lato sinistro non era solo quello di produrre dati sull'output standard, un errore sul lato sinistro è un vero errore che dovrebbe essere segnalato.
In semplice sh, l'unica soluzione è usare una pipe con nome.
set -e
mkfifo p
command1 >p & pid1=$!
command2 <p
wait $pid1
In ksh, bash e zsh, è possibile indicare alla shell di uscire da una pipeline con uno stato diverso da zero se qualsiasi componente della pipeline esce con uno stato diverso da zero. Devi impostare l' pipefail
opzione:
- ksh:
set -o pipefail
- bash:
shopt -s pipefail
- zsh:
setopt pipefail
(o setopt pipe_fail
)
In mksh, bash e zsh, è possibile ottenere lo stato di ogni componente della pipeline utilizzando la variabile PIPESTATUS
(bash, mksh) o pipestatus
(zsh), che è un array contenente lo stato di tutti i comandi nell'ultima pipeline (una generalizzazione di $?
).
which lss | echo $?
,echo
viene avviato prima chewhich
sia terminato; la shell che genera la riga di comandoecho
non ha modo di sapere quale sarà lo stato di uscitawhich
in seguito.