O status de saída de um tubo é o status de saída do comando à direita. O status de saída do comando esquerdo é ignorado.
(Observe que which lss | echo $?
não mostra isso. Você executaria which lss | true; echo $?
para mostrar isso. Em which lss | echo $?
, echo $?
relata o status do último comando antes deste pipeline.)
A razão pela qual os shells se comportam dessa maneira é que existe um cenário bastante comum em que um erro no lado esquerdo deve ser ignorado. Se o lado direito sair (ou mais geralmente fechar sua entrada padrão) enquanto o lado esquerdo ainda estiver gravando, o lado esquerdo receberá um sinal SIGPIPE. Nesse caso, geralmente não há nada errado: o lado direito não se importa com os dados; se o papel do lado esquerdo é apenas produzir esses dados, não há problema em parar.
No entanto, se o lado esquerdo morrer por algum motivo que não seja o SIGPIPE, ou se o trabalho do lado esquerdo não for apenas produzir dados na saída padrão, um erro no lado esquerdo é um erro genuíno que deve ser relatado.
No sh simples, a única solução é usar um pipe nomeado.
set -e
mkfifo p
command1 >p & pid1=$!
command2 <p
wait $pid1
No ksh, bash e zsh, você pode instruir o shell a fazer com que um pipeline saia com um status diferente de zero se algum componente do pipeline sair com um status diferente de zero. Você precisa definir a pipefail
opção:
- ksh:
set -o pipefail
- bater:
shopt -s pipefail
- zsh:
setopt pipefail
(ou setopt pipe_fail
)
No mksh, bash e zsh, você pode obter o status de cada componente do pipeline usando a variável PIPESTATUS
(bash, mksh) ou pipestatus
(zsh), que é uma matriz que contém o status de todos os comandos no último pipeline (uma generalização de $?
)
which lss | echo $?
, oecho
é iniciado antes dewhich
sair; o shell que está gerando a linha de comandoecho
não tem como saber qual será o status de saídawhich
posteriormente.