Der Dokumentation zufolge wartet die Bash, bis alle Befehle in einer Pipeline ausgeführt wurden, bevor sie fortgesetzt werden
Die Shell wartet, bis alle Befehle in der Pipeline beendet sind, bevor sie einen Wert zurückgibt.
Warum wird der Befehl dann yes | true
sofort beendet? Sollte die yes
Schleife nicht für immer andauern und die Pipeline niemals zurückkehren lassen?
Und eine Unterfrage: Gemäß der POSIX-Spezifikation können Shell-Pipelines entweder nach Beendigung des letzten Befehls zurückkehren oder warten, bis alle Befehle beendet sind. Haben gemeinsame Muscheln in diesem Sinne ein unterschiedliches Verhalten? Gibt es Muscheln, in denen yes | true
eine Endlosschleife erstellt wird?
yes | tee >(true) >/dev/null
wird übrigens sotee
weiter machen, wie Sie es erwarten, bis alle Autoren tot sindtrue
.true
ist im Grunde ein{return 0;}
Programm, also würde ich nicht erwarten, dass es lange läuft, geschweige denn für immer.Antworten:
Beim
true
Verlassen wird die Leseseite der Pipe geschlossen, es wird jedochyes
weiterhin versucht, auf die Schreibseite zu schreiben. Dieser Zustand wird als "broken pipe" bezeichnet und veranlasst den Kernel, einSIGPIPE
Signal an zu sendenyes
. Dayes
dieses Signal nichts Besonderes tut, wird es getötet. Wenn es das Signal ignoriert, schlägt seinwrite
Aufruf mit Fehlercode fehlEPIPE
. Programme, die dies tun, müssen darauf vorbereitet sein, dass sie es bemerkenEPIPE
und aufhören zu schreiben, sonst geraten sie in eine Endlosschleife.Wenn Sie
strace yes | true
1 tun , können Sie sehen, wie sich der Kernel auf beide Möglichkeiten vorbereitet:strace
überwacht Ereignisse über die Debugger-API, die zuerst über den Systemaufruf informiert, der mit einem Fehler zurückkehrt, und dann über das Signal. Ausyes
der Sicht von 's geschieht das Signal jedoch zuerst. (Technisch gesehen wird das Signal geliefert, nachdem der Kernel die Steuerung an den Benutzerbereich zurückgegeben hat, aber bevor weitere Maschinenanweisungen ausgeführt werden, sodass diewrite
"Wrapper" -Funktion in der C-Bibliothek keine Möglichkeit erhälterrno
, die Anwendung festzulegen und zur Anwendung zurückzukehren.)1 Leider
strace
ist Linux-spezifisch. Die meisten modernen Unixe haben einen Befehl, der etwas Ähnliches tut, aber oft einen anderen Namen hat, Syscall-Argumente wahrscheinlich nicht so gründlich dekodiert und manchmal nur für root funktioniert.quelle
yes
der Pipe verbunden ist.yes
dass SIGPIPE abgerufen wird, da der FD, auf den geschrieben wird, nicht mit einer Pipe verbunden ist.yes >/dev/null
für immer. Es zeigt überhaupt nichts über Pipelines, was nicht auch für einfache Befehle gilt (wie das Verhalten beim Warten auf Beendigung, das Tom hervorhebt, gilt auch für einfache Befehle).write()
kehrt die Funktion in libc erst nachher zurück (Übertragung der Kontrolle auf den darauf folgenden PC) Der Signalhandler wurde ausgeführt, aber da der Signalhandler das Programm beendet, wird die Steuerung niemals übertragen undwrite()
kehrt daher niemals zurück. Ja, das wird im Kernel implementiert, indem einexxx_write()
Funktion zurückgegeben wird-EPIPE
, aber wir debuggen ein User-Space-Programm und sind daran nicht interessiert.Unwahrscheinlich, da der
yes
Befehl die Pipe verwendet und sie fehlschlägt, wenn die Pipe unterbrochen ist.sleep
benutzt die Pipe dagegen nicht, also:läuft mindestens 100000000 Sekunden lang.
quelle
true
sich ein eingebauter befindet. Dies gilt für die neueren Versionen von derBourne Shell
,ksh93
,zsh
. Wenn Sie^Z
bei Ausführung eines solchen Befehls drücken, wird der Energiesparmodus unterbrochen, und die Shell kann ohne externe Hilfe keine Wiederherstellung durchführen.sbrk()
. Eine portable und gepflegte Version ist im schily tools Bundle enthalten und @Charles Duffy hat bereits einen Ort für Informationen gefunden ;-)bsh
zurückportiert habe, stammen von mir (Berthold Shell von VBERTOS, einer mit virtuellem Speicher ausgestatteten Version von UNOS - dem ersten UNIX-Klon). Bsh erhielt 1984 und 1985 viele csh-Funktionen, aber der Alias-Mechanismus von UNOS war bereits 1980 dem von csh überlegen. Andere neue Bourne Shell-Funktionen stammen von POSIX, damit POSIX-Konformität erreicht wird.