Beim Experimentieren mit der Umleitung von Ausgaben und der Substitution von Prozessen bin ich auf den folgenden Befehl und die daraus resultierende Ausgabe gestoßen:
me @ elem: ~ $ echo foo >> (cat); Echobar Bar me @ elem: ~ $ foo
(Ja, diese leere Zeile am Ende ist beabsichtigt.)
Bash-Echo-Leiste, druckt meine übliche Eingabeaufforderung, Echo-Foo, Echo ist eine neue Zeile und lässt meinen Cursor dort. Wenn ich erneut die Eingabetaste drücke, wird meine Eingabeaufforderung in einer neuen Zeile gedruckt und der Cursor folgt ihr (wie erwartet, wenn jemand in einer leeren Befehlszeile die Eingabetaste drückt).
Ich hatte erwartet, dass es foo in einen Dateideskriptor schreibt, cat es liest und echo's foo, die Leiste des zweiten Echoechos, und dann zurück zur Eingabeaufforderung. Das ist aber eindeutig nicht der Fall.
Könnte jemand bitte erklären, was los ist?
quelle
Antworten:
Je nach Zeitpunkt wird möglicherweise
foo
vorbar
, nachbar
oder sogar nach der Eingabeaufforderung angezeigt . Fügen Sie eine kleine Verzögerung hinzu, um ein konsistentes Timing zu erhalten:bar
erscheint sofort, dannfoo
nach einer Sekunde, dann die nächste Eingabeaufforderung nach einer weiteren Sekunde.Was passiert ist, dass bash Prozessersetzungen im Hintergrund ausführt.
sleep 1; cat
und richtet eine Pipe dazu ein.echo foo
. Da dies den Pipe-Puffer nicht ausfüllt, wird derecho
Befehl ohne Blockierung beendet.echo bar
.sleep 2
.sleep 1
.sleep 1
Kehrt nach ca. 1 Sekunde in den Unterprozess zurück. Der Unterprozess wird fortgesetztcat
.cat
kopiert seine Eingabe in seine Ausgabe (die auf dem Bildschirm angezeigt wird) und kehrt zurück.sleep 2
kehrt zurück. Der Haupt-Shell-Prozess wird ausgeführt und Sie sehen die nächste Eingabeaufforderung.quelle
Sie benötigen keine Prozessersetzung, um diesen Effekt zu erzielen. Versuche dies:
Sie erhalten fast das gleiche Ergebnis (ohne das
bar
; ich lasse das als Übung) und aus dem gleichen Grund. In beiden Fällencat
wird als Hintergrundaufgabe gestartet. In meiner Zeile hier ist das explizit. Im Fall der Prozessersetzung ist dies ebenfalls explizit - es handelt sich um einen separaten Prozess, der an einen Namensdateideskriptor angehängt ist -, aber möglicherweise nicht so offensichtlich.Der untergeordnete Prozess wird nicht unbedingt beendet, bevor
bash
die nächste Eingabeaufforderung gedruckt wird. Und da seine Ausgabe gepuffert ist, gibt es nichts aus, bis es beendet wird. Zu diesem Zeitpunkt wurde bash gerade$
auf stderr gedruckt , und jetzt wird der Hintergrundprozess nach dem Druckenfoo
und einer neuen Zeile beendet.quelle