Ich versuche, SIGPIPE unter Linux besser zu verstehen.
Ich habe dieses Experiment ausgeführt: { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head
und es gibt ein Echo aus 141
, was meines Wissens nach ein Exit-Code ist, der Prozessen zugewiesen wird, die mit beendet werden. SIGPIPE
Zuvor habe ich dies häufig gemacht, ohne die Nuancen von zu verstehen, SIGPIPE
und normalerweise verwende ich set -eEuo pipefail
es. Ich habe also versucht zu verstehen, warum mein Code nicht ständig aufgrund defekter Pipes fehlschlug ... Also habe ich dieses andere Experiment ausgeführt: ( set -o pipefail; { ls -al /tmp/ ; echo "$?" 1>&2 ; } | head; )
und dieses Mal habe ich eine 0 im Echo erhalten ... wenn also pipefail
aktiviert ist, bedeutet das, dass SIGPIPE
unterdrückt wird? Oder verstehe ich falsch, was hier vor sich geht?
Antwort1
ls
kann möglicherweise die gesamte Ausgabe schreiben, bevor head
es beendet wird und die Pipe unterbricht, selbst wenn die Ausgabe ls
länger ist als das, was head
gedruckt wird. Dies liegt daran:
head
kann mehr lesen als es schließlich ausdrucken wird,- und einen Puffer für das Rohr gibt es sowieso.
SIGPIPE wird durch tatsächliches Schreiben in eine defekte Pipe ausgelöst. Wenn ls
es gelingt, die gesamte Ausgabe vor head
dem Beenden zu schreiben, gibt es keinen Schreibvorgang, der SIGPIPE auslöst.
Oder ls
es gelingt ihm möglicherweise nicht, die gesamte Ausgabe zu schreiben, bevor head
es beendet wird. Dann wird versucht, mehr zu schreiben und es wird SIGPIPE angezeigt.
Da ls
und head
parallel laufen, besteht meiner Meinung nach im Allgemeinen ein Race Condition. Es kann vorkommen, dass eine bestimmte Ausgabe von ls
SIGPIPE zufällig auslöst oder nicht.
Versuchen Sie es mit yes
statt mit ls …
:
{ yes ; echo "$?" 1>&2 ; } | head
oder
( set -o pipefail; { yes ; echo "$?" 1>&2 ; } | head; )
yes
generiert eine Ausgabe, die nicht von selbst endet, sodass nach head
dem Beenden immer ein Schreibvorgang erfolgt, der SIGPIPE auslöst. Jeder der oben genannten Befehle gibt Ihnen dies 141
mit Sicherheit.
Das hat nichts damit zu tun pipefail
.