"Rohrbruch" in dieser Situation zu sehen, ist selten, aber normal.
Wenn Sie ausführen type rvm | head -1
, wird die Bash type rvm
in einem Prozess head -1
in einem anderen ausgeführt. 1 Der stdout von type
ist mit dem "write" -Ende einer Pipe verbunden , der stdin head
mit dem "read" -Ende. Beide Prozesse laufen gleichzeitig ab.
Der head -1
Prozess liest Daten aus stdin (normalerweise in Stücken von 8 kB), druckt eine einzelne Zeile aus (je nach -1
Option) und wird beendet, wodurch das "Lese" -Ende der Pipe geschlossen wird. Da die rvm
Funktion ziemlich lang ist (etwa 11 kB, nachdem sie durch Bash analysiert und rekonstruiert wurde), bedeutet dies, dass sie beendet wird, head
während type
noch ein paar kB Daten zum Schreiben vorhanden sind.
Da type
versucht wird, in eine Pipe zu schreiben, deren anderes Ende geschlossen wurde - eine unterbrochene Pipe -, gibt die Funktion write (), die sie aufgerufen hat, einen EPIPE-Fehler zurück, der als "unterbrochene Pipe" übersetzt wird. Zusätzlich zu diesem Fehler sendet der Kernel auch das Signal SIGPIPE an type
, wodurch der Prozess standardmäßig sofort abgebrochen wird .
(Das Signal ist in interaktiven Shells sehr nützlich, da die meisten Benutzer nicht möchten, dass der erste Prozess weiterläuft und versucht, ins Nirgendwo zu schreiben. In der Zwischenzeit ignorieren nicht interaktive Dienste SIGPIPE - es wäre nicht gut, wenn ein Daemon lange läuft bei so einem einfachen Fehler sterben - so finden sie den Fehlercode sehr nützlich.)
Die Signalübermittlung erfolgt jedoch nicht zu 100% sofort, und es kann Fälle geben, in denen write () EPIPE zurückgibt und der Prozess vor dem Empfang des Signals eine kurze Zeit lang weiterläuft. In diesem Fall type
bleibt genügend Zeit, um den fehlgeschlagenen Schreibvorgang zu bemerken, den Fehlercode zu übersetzen und sogar eine Fehlermeldung an stderr zu drucken, bevor er von SIGPIPE beendet wird. (Die Fehlermeldung lautet "-bash: type:", da dies type
ein integrierter Befehl von bash selbst ist.)
Dies scheint auf Multi-CPU-Systemen häufiger zu sein, da der type
Prozess und der Signalübermittlungscode des Kernels buchstäblich gleichzeitig auf verschiedenen Kernen ausgeführt werden können.
Es wäre möglich, diese Nachricht zu entfernen, indem Sie den type
eingebauten Code (im Bash-Quellcode) patchen , damit er sofort beendet wird, wenn er eine EPIPE von der write () -Funktion empfängt.
Es gibt jedoch keinen Grund zur Sorge und es hängt rvm
in keiner Weise mit Ihrer Installation zusammen.
ls
through weitergeleitethead -1
, und heute erhalte ich eine kaputte Pipe-Meldung.Sie können einen Rohrbruch auf Kosten eines anderen Prozesses beheben, indem Sie
tail -n +1
in Ihr Rohr Folgendes einfügen :Das
+1
weist Sietail
an, die erste Eingabezeile und alles, was folgt , zu drucken. Die Ausgabe ist genau so, als wäre sietail -n +1
nicht vorhanden, aber das Programm ist intelligent genug, um die Standardausgabe zu überprüfen und die Pipe sauber zu schließen. Keine kaputten Rohre mehr .quelle
find /var/lib/mysql -xdev -type f -daystart -mmin +5 -print0 | xargs -0 ls -ldt | tail -n +1 | head
zuverlässig ergibtxargs: ls: terminated by signal 13
. Wie wir wissen, liegt das Problem in der Erschöpfung der Eingabe und es gibt wirklich nur einen Befehl, der sich mit dem Puffern befasst: dd. Das Hinzufügen| dd obs=1M
zur Pipeline behebt die SIGPIPE für meinen Anwendungsfall.type rvm | (head -1 ; dd of=/dev/null)
Das ist natürlich, für andere Vorschläge ähnlich ist , wie es alle Eingangs verursacht verarbeitet werden ,dd
sollte aber das effizienteste Programm sein, um mit solchen Dingen umzugehen.Die
write error: Broken pipe
Nachricht bezieht sich auf einen Schreibvorgang, bei dem versucht wird, in eine Pipe zu schreiben, ohne dass am Leseende dieser Pipe noch Leser übrig sind, und auf den besonderen Umstand, dass dasSIGPIPE
Signal so eingestellt ist, dass es entweder vom aktuellen oder vom übergeordneten Prozess ignoriert wird. Wenn es der übergeordnete Prozess war,SIGPIPE
der ignoriert wurde, kann der untergeordnete Prozess dies in einer nicht-interaktiven Shell nicht wieder rückgängig machen.Es ist jedoch möglich, das Programm mit expliziten Subshells zu beenden ,
type rvm
wenn eshead -1
beendet wird. Auf diese Weise können wir einen Hintergrund erstellen, eine Nachricht an die Subshelltype rvm
senden und dort eine Trap implementieren , um explizit zu töten .typepid
head -1
EXIT
type rvm
quelle
type
genügend Zeit, um den fehlgeschlagenen Schreibvorgang zu bemerken, den Fehlercode zu übersetzen und sogar eine Fehlermeldung an stderr zu drucken, bevor Sie von SIGPIPE getötet werden . Ich denke, Ihre Lösung hindert den Producer- Prozess (type
hier) nicht daran, auf das fehlgeschlagene Schreiben (aufgrund einer geschlossenen Pipe) zu reagieren, oder?