Wie kommt es, dass „while true; do echo y; done | true“ von selbst beendet wird, „while true; do echo y | cat; done | true“ jedoch nicht?

Wie kommt es, dass „while true; do echo y; done | true“ von selbst beendet wird, „while true; do echo y | cat; done | true“ jedoch nicht?

Um die Frage im Titel klarzustellen: Ich verstehe, warum Ersteres stirbt. Ich verstehe nicht, warum Letzteres nicht stirbt, nur weil ein | catzum Schleifenkörper hinzugefügt wird.

Auch vielleicht damit verbunden,

while true; do echo y; done

stirbt sofort, wenn ich das tue ^C, aber das Töten

while true; do echo y | cat; done

oft muss man ^Cmehr als einmal drücken. Manchmal klappt es einmal, manchmal 2 oder 3 Mal, und dann gibt es Zeiten, in denen ich ^Ceine Weile warten muss, bis es stirbt.

Beide Verhaltensweisen treten sowohl bei Bash als auch bei Zsh auf, obwohl das ^Ceine bei Bash seltener aufzutreten scheint.

Für beide Verhaltensweisen ist dies nicht auf das Hinzufügen des Pipe-Zeichens beschränkt cat. | dd, | tee, usw. verursachen sie auch. echo y | trueEs verursacht sie sogar. Es scheint die Anwesenheit eines Pipe-Zeichens im Schleifenkörper zu sein.

Warum ändert das Vorhandensein eines Rohrs in einem Schleifenkörper die Reaktion der Schleife auf Signale?

Antwort1

while true; do echo y; done | trueDa in echointegriert ist, können Sie einen Subshell-Prozess ausführen, der y\nin einer Schleife in eine Pipe schreibt.

Bei trueder Rückkehr ist das Leseende dieser Pipe geschlossen, sodass das Schreiben an das Schreibende dazu führt, dass ein SIGPIPEan den Schreibprozess übergeben wird. Hier ist das der Subshell-Prozess, der die Schleife ausführt.

In while true; do echo y | cat; done | trueist es catdas, was in die Pipe schreibt. catist im Allgemeinen nicht integriert, und selbst wenn es das wäre, werden in anderen Shells als zsh und ksh alle Pipe-Komponenten immer in untergeordneten Prozessen ausgeführt.

Hier wird also nur der laufende Prozess catbeendet und der Subshell-Prozess, der die Schleife ausführt, führt weiterhin weitere catProzesse aus, die beendet werden, sobald sie y\nauf ihre Standardausgabe schreiben.

Wenn Sie in ksh93/ksh2020 Folgendes tun:

$ builtin cat
$ type cat
cat is a shell builtin
$ set -o pipefail
$ while true; do echo y | cat; done | true; kill -l "$?"
PIPE

Dieses Mal catist es integriert und wird im selben Prozess wie die Schleife ausgeführt (wie auch catder Befehl ganz rechts in der ersten Pipezeile, und ksh führt diesen nicht in einer Subshell aus), sodass die Subshell-Pipes truebeendet werden und kill -lbestätigen, dass sie durch ein SIGPIPE beendet wurde.

verwandte Informationen