Ist es möglich, die Ausgabe eines Befehls in mehrere Befehle umzuleiten?

21

Soweit ich weiß, kann ich mit dem Befehl tee die Standardausgabe auf den Bildschirm und weitere Dateien aufteilen:

command -option1 -option2 argument | tee file1 file2 file3 

Ist es möglich, die Ausgabe mit tee auf Befehle anstatt auf Dateien umzuleiten, sodass ich theoretisch eine Befehlskette erstellen kann?

Abdul Al Hazred
quelle
3
Erläutern Sie, was Sie unter "Ausgangssignal" verstehen, und beschreiben Sie, was Sie unter "Netzwerk von Befehlen" verstehen.
Janis
unter linux hat jeder befehl einen eingang und zwei ausgänge. Sie sind mit 0 (für die Eingabe), 1 (für die Ausgabe) und 2 (für die Fehlerausgabe) gekennzeichnet. Ich dachte an 1, als ich "Ausgangssignal" sagte, weil ich las, dass der Befehl tee nur den mit 1 bezeichneten Ausgang aufteilt. Als ich "Netzwerk von Befehlen" sagte, war ich nicht sehr technisch, ich bin nicht sicher, wie das Netzwerk korrekt definiert ist Eine mathematische Sichtweise, aber ich dachte nur typologisch an einen Baum von Befehlen, so dass einige Befehle Eltern von mehr als einem untergeordneten Befehl sein können.
Abdul Al Hazred
Vielen Dank für Ihre Klarstellung. Bitte verwenden Sie das Wort signal nicht, da es in Unix eine bestimmte Bedeutung hat und der Begriff in diesem Zusammenhang sehr irreführend war. Danke noch einmal.
Janis
Geben Sie in der Befehlszeile das Zeichen man -k ein, um die besondere Bedeutung dieses Schlüsselkonzepts unter UNIX und Linux zu erfahren. man kill wäre eine gute seite, um damit anzufangen.
Rob
Viele Leute bezeichnen stdin stdout und stderr auch als Eingabe- oder Ausgabe-Streams. Es gibt wie kleine Flüsse von Daten daher einen Strom. Sie haben zu Recht nach einem Wort gegriffen, um es gemeinsam zu beschreiben, aber signal ist einfach das falsche Wort.
Rob

Antworten:

25

Sie können Named Pipes ( http://linux.die.net/man/1/mkfifo ) in der Befehlszeile von verwenden teeund die Befehle in den Named Pipes lesen lassen.

mkfifo /tmp/data0 /tmp/data1 /tmp/data2
cmd0 < /tmp/data0 & cmd1 < /tmp/data1 & cmd2 < /tmp/data2 &
command -option1 -option2 argument | tee /tmp/data0 /tmp/data1 /tmp/data2

Wenn der commandVorgang abgeschlossen ist, teewerden die benannten Pipes geschlossen, wodurch ein EOF (Lesen von 0 Bytes) für jedes der Pipes signalisiert wird, das /tmp/dataNnormalerweise die cmdNProzesse beenden würde . Reales Beispiel:

$ mkfifo /tmp/data0 /tmp/data1 /tmp/data2
$ wc -l < /tmp/data0 & wc -w < /tmp/data1 & wc -c < /tmp/data2 &
$ tee /tmp/data0 /tmp/data1 /tmp/data2 < /etc/passwd >/dev/null
$ 61
1974
37

Aufgrund der Hintergrundprozesse gab die Shell vor der Programmausgabe eine Eingabeaufforderung zurück. Alle drei Instanzen von wurden wcnormal beendet.

Arcege
quelle
1
In Bash können Sie viel Tippen über sparen /tmp/data/{0,1,2}. Andererseits könnte man in bash die Prozessersetzung verwenden und mkfifoganz überspringen
Tobias Kienzler
2
Möglicherweise möchten Sie / dev / data0 in / tmp / data0 ändern. Vielen Dank auch für die muschelunabhängige Beantwortung der Frage. Das ist hilfreicher, als davon auszugehen, dass alle bash verwenden.
abonet
15

Wenn ich richtig verstehe, sind Sie für das Äquivalent tee file1 file2 file3, sondern als Schreib die gleichen Daten zu drei Dateien file1, file2und file3, Sie Rohr wollen die gleichen Daten in drei Befehle cmd1, cmd2und cmd3, das heißt

… | ??? cmd1 cmd2 cmd3

sollte gleichbedeutend sein mit

… | cmd1 &
… | cmd2 &
… | cmd3 &

außer das würde nur einmal ausgeführt werden.

Dafür gibt es zwei Möglichkeiten.

Ksh93, bash und zsh unterstützen die Prozessersetzung . Dies ist eine Verallgemeinerung von Pipes, die es dem Argument eines Befehls ermöglicht, eine Datei zu sein, in die beim Schreiben Daten als Eingabe an einen Befehl übergeben werden. . Das ist,

echo hello | tee >(cmd1)

druckt helloauf Standardausgabe und läuft zusätzlich cmd1mit helloals Eingabe.

So zum Beispiel, wenn Sie die Eingabe von duplizieren wollen somecommandund gibt es an beide cmd1und cmd2können Sie verwenden

somecommand | tee >(cmd1) | cmd2

Wenn Ihre Shell keine Prozessersetzung unterstützt, können Sie stattdessen Named Pipes verwenden. Siehe Arcege Antwort , wie das funktioniert. Named Pipes sind weniger praktisch als die Prozessersetzung, da Sie sie erstellen und löschen sowie Prozesse manuell starten und synchronisieren müssen. Sie haben den Vorteil, dass sie vollständig portierbar sind, während nicht alle Shells Prozessersetzungen unterstützen. Sie können auch in anderen Szenarien als denen verwendet werden, für die die Prozessersetzung vorgesehen ist.

Unter der Haube werden bei einigen Systemen für die Prozessersetzung intern Named Pipes verwendet. Auf den meisten Systemen werden jedoch benannte Dateien verwendet, die Dateideskriptoren darstellen .

Gilles 'SO - hör auf böse zu sein'
quelle
5
Siehe auch peevon moreutils.
Stéphane Chazelas
Beachten Sie, dass die Prozessersetzung durch ksh88 eingeführt wurde.
Stéphane Chazelas
6

Zumindest in der Sie mkfifomit der Prozessersetzung überspringen :

command -option1 -option2 argument | tee >(cmd1) >(cmd2) >(cmd3)

oder um das Beispiel von Arcege anzunehmen

tee >(wc -l) >(wc -w) >(wc -c) < /etc/passwd >/dev/null
Tobias Kienzler
quelle