L'état de sortie d'un tuyau est l'état de sortie de la commande de droite. Le statut de sortie de la commande de gauche est ignoré.
(Notez que which lss | echo $?
cela ne s'affiche pas. Vous devez exécuter which lss | true; echo $?
pour afficher cela. Dans which lss | echo $?
, echo $?
indique l'état de la dernière commande avant ce pipeline.)
La raison pour laquelle les shells se comportent de cette façon est qu'il existe un scénario assez courant où une erreur dans la partie gauche doit être ignorée. Si le côté droit sort (ou ferme plus généralement son entrée standard) pendant que le côté gauche écrit toujours, alors le côté gauche reçoit un signal SIGPIPE. Dans ce cas, il n'y a généralement rien de mal: le côté droit ne se soucie pas des données; si le rôle du côté gauche est uniquement de produire ces données, il est normal que cela s'arrête.
Cependant, si le côté gauche meurt pour une raison autre que SIGPIPE, ou si le travail du côté gauche n'était pas uniquement de produire des données sur la sortie standard, une erreur dans le côté gauche est une véritable erreur qui doivent être signalés.
En clair, la seule solution est d'utiliser un tube nommé.
set -e
mkfifo p
command1 >p & pid1=$!
command2 <p
wait $pid1
Dans ksh, bash et zsh, vous pouvez demander au shell d'effectuer une sortie de pipeline avec un statut différent de zéro si un composant du pipeline se termine avec un statut différent de zéro. Vous devez définir l' pipefail
option:
- ksh:
set -o pipefail
- frapper:
shopt -s pipefail
- zsh:
setopt pipefail
(ou setopt pipe_fail
)
Dans mksh, bash et zsh, vous pouvez obtenir l'état de chaque composant du pipeline à l'aide de la variable PIPESTATUS
(bash, mksh) ou pipestatus
(zsh), qui est un tableau contenant l'état de toutes les commandes du dernier pipeline (une généralisation de $?
).
which lss | echo $?
, leecho
est démarré avantwhich
sa sortie; le shell générant la ligne de commande pourecho
n'a aucun moyen de savoir quel sera le statut de sortie dewhich
plus tard.