
yes "test" | grep -m3 "test"
druckt
test
test
test
und dann endet. Dasselbe gilt
yes "test" | while read line; do echo $line; done | grep -m3 "test"
Und
yes "test" | while read line; do echo $line; done | grep -E "*" | grep -m3 "test"
Aber
yes "test" | while read line; do echo $line | grep -E "*"; done | grep -m3 "test"
druckt
test
test
test
und bleibt dann hängen. Was ist hier los?
Antwort1
In
ja "testen" | während Zeile lesen; mache Echo $Zeile; fertig | grep -E "*" | grep -m3 "testen"Es gibt vier Prozesse, die ausgeführt werden
yes
, das Shell-Programm, das diese while
Schleife ausführt, grep
und grep
. Der letzte Prozess in der Pipeline wird beendet und schließt das Leseende seiner Eingabepipe nach drei Übereinstimmungen. Die Pipeline wird dann durch eine Kette von SIGPIPE
s beendet, wie es für vorzeitig beendete Pipelines üblich ist, da jede Stufe der Pipeline wiederum in eine defekte Pipe schreibt.
In
ja "testen" | während Zeile gelesen wird; mache echo $line | grep -E "*"; fertig | grep -m3 "testen"Es laufen drei Prozesse
yes
, das Shell-Programm und grep
. Aber der zweite Prozess, der das Shell-Programm ausführt, erzeugt ständig zweiweiteruntergeordnete Prozesse, einer führt die echo
und einer eine andere grep
Instanz aus. Letzterer Prozess sendet die SIGPIPE
undnichtder Prozess, der das Shell-Programm ausführt. Es ist dieser letztere Prozess, der tatsächlich in die defekte Pipe schreibt.
Die Folge davon ist, dass die zweite Stufe der Pipeline, die Shell, die diese while
Schleife ausführt, niemalsselbstbeendet SIGPIPE
und läuft einfach weiter, wobei eine untergeordnete Pipeline erzeugt wird; immer und immer wieder. Es sieht, dass die untergeordnete Pipeline, die es erzeugt hat, SIGPIPE
natürlich mit einem endet, aber für die Shell, die die while
Schleife ausführt, ist dasnichtein Grund, die Schleife zu beenden.