Статус выхода канала — это статус выхода правой команды. Статус выхода левой команды игнорируется.
(Обратите внимание, что what lss | echo $?
этого не показывает. Вы должны запустить what lss | true; echo $?
, чтобы показать это. В which lss | echo $?
, echo $?
сообщает о состоянии последней команды перед этим конвейером.)
Причина, по которой оболочки ведут себя таким образом, заключается в том, что существует довольно распространенный сценарий, при котором возникает ошибка. в левой части следует игнорировать. Если правая сторона выходит (или, в более общем случае, закрывает свой стандартный ввод), в то время как левая сторона все еще записывает, то левая сторона получает сигнал SIGPIPE. В этом случае обычно нет ничего плохого: правая часть не заботится о данных; если роль левой стороны состоит исключительно в том, чтобы производить эти данные, то она может остановиться.
Однако, если левая сторона умирает по какой-либо причине, отличной от SIGPIPE, или если задача левой стороны заключалась не только в создании данных на стандартном выходе, то ошибка в левой части является ошибкой. подлинная ошибка, о которой следует сообщить.
В простом sh единственным решением является использование именованного канала.
set -e
mkfifo p
command1 >p & pid1=$!
command2 <p
wait $pid1
В ksh, bash и zsh вы можете указать оболочке сделать выход конвейера с ненулевым статусом, если какой-либо компонент конвейера завершается с ненулевым статусом.Вам необходимо установить параметр pipefail
:
set -o pipefail
shopt -s pipefail
setopt pipefail
] (или setopt pipe_fail
) В mksh, bash и zsh вы можете получить статус каждого компонента конвейера, используя переменную PIPESTATUS
(bash, mksh) или pipestatus
(zsh), который представляет собой массив, содержащий статус всех команд в последнем конвейере (обобщение $?
).