In zsh ist der Unterschied zwischen cat <(cat) vs cat | Katze gegen Katze = (Katze)?

18

Ich erwartete cat <(cat)und sollte cat | catdasselbe tun: Zeilen von stdin nach stdout kopieren. Mein Verständnis war, dass beide a catin einer Subshell ausführen , die catstdout der Subshell auf eine temporäre Named Pipe umleiten und dann eine andere catin der aktuellen Shell ausführen, deren stdin auf die Pipe umgeleitet wird.

cat <(cat)Lassen Sie mich stattdessen an meinem Terminal tippen, aber keine der Eingabezeilen wird kopiert und es wird ^Dkein Signal EOFausgegeben. cat | catfunktioniert aber wie erwartet.

Als weiteres Experiment habe ich geprüft, ob cat =(cat)ähnliche Schwierigkeiten wie cat <(cat)vorliegen, aber es funktioniert wie erwartet: Bis zu einem ^Dwird alles auf einmal auf stdout kopiert.

Kann mir jemand helfen zu verstehen, was zsh unter der Haube tut?

Alan O'Donnell
quelle

Antworten:

23
  1. a | bverbindet STDOUTvon aund STDINvon bnur mit dup/dup2. Beide Befehle werden parallel ausgeführt.

  2. a =(b)Ersetzt das Argument to adurch einen temporären Dateinamen. bwird ausgeführt, bevor adie temporäre Datei erstellt werden muss, bevor sie an übergeben werden kanna

  3. a <(b)Ersetzt das Argument to adurch eine Named Pipe. aund bparallel laufen. Hier wird es jetzt etwas komplizierter:

    bbefindet sich im Hintergrund und kann nicht vom Terminal lesen. Sie können es selbst testen, indem Sie strace -p $PIDan Ihren zweiten Katzenprozess anhängen, um den Prozess zu sehen.

    aversucht in der Zwischenzeit, aus der Named Pipe zu lesen, kann aber nichts lesen wie bnicht lesen.

    • Dies bedeutet, dass Sie im Grunde genommen einen Deadlock haben, bei dem aversucht wird zu lesen, baber bnicht gelesen STDINund nicht beschrieben werden kanna

Weitere Informationen zum Hintergrundprozess und Terminal von man bash :

Um die Implementierung der Benutzerschnittstelle zur Auftragssteuerung zu erleichtern, behält das Betriebssystem den Begriff einer aktuellen Terminalprozessgruppen-ID bei . Mitglieder dieser Prozessgruppe (Prozesse, deren Prozessgruppen-ID der aktuellen Prozessgruppen-ID des Terminals entspricht) erhalten über die Tastatur generierte Signale wie SIGINT . Diese Prozesse sollen im Vordergrund stehen . HintergrundProzesse sind solche, deren Prozessgruppen-ID von der des Terminals abweicht. Solche Prozesse sind immun gegen tastaturgenerierte Signale. Nur Vordergrundprozesse dürfen aus dem Terminal lesen oder, wenn der Benutzer dies mit stty tostop angibt, in das Terminal schreiben. Hintergrundprozesse, die versuchen, aus dem Terminal zu lesen (zu schreiben, wenn stty tostop aktiv ist ) , erhalten vom Terminal-Treiber des Kernels ein SIGTTIN- Signal (SIGTTOU) , das den Prozess anhält , sofern es nicht abgefangen wird.

Ulrich Dangel
quelle
Großartig, danke - das hat viel aufgeklärt!
Alan O'Donnell
1
Beachten Sie, dass zsh, wenn es nicht interaktiv ist, die Standardeingabe von Hintergrundbefehlen (einschließlich der in <(cmd)) an umleitet /dev/null, sodass das Verhalten zsh -c 'cat <(cat)'anders ist ( sofort zurückgegeben und nichts ausgegeben).
Stéphane Chazelas