Frage Wie verbinde ich zwei benannte Pipes in einzelnen Input-Stream in Linux


Verwenden der Rohre (|) Feature in Linux kann ich die Standardeingabe an einen oder mehrere Ausgabeströme weiterleiten.

ich kann nutzen tee um die Ausgabe in separate Teilprozesse aufzuteilen.

Gibt es einen Befehl, zwei Eingabestreams zu verbinden?

Wie würde ich darüber gehen? Wie funktioniert das Diff?


59
2017-08-16 17:29


Ursprung




Antworten:


Persönlich, mein Favorit (benötigt Bash und andere Dinge, die bei den meisten Linux-Distributionen Standard sind)

Die Details können sehr davon abhängen, was die beiden Dinge ausgeben und wie Sie sie zusammenführen wollen ...

Inhalt von command1 und command2 hintereinander in der Ausgabe:

cat <(command1) <(command2) > outputfile

Oder wenn beide Befehle alternative Versionen derselben Daten ausgeben, die Sie nebeneinander sehen möchten (ich habe dies mit snmpwalk verwendet; Zahlen auf der einen und MIB-Namen auf der anderen Seite):

paste <(command1) <(command2) > outputfile

Oder wenn Sie die Ausgabe von zwei ähnlichen Befehlen vergleichen möchten (sagen wir einen Fund in zwei verschiedenen Verzeichnissen)

diff <(command1) <(command2) > outputfile

Oder wenn sie geordnete Ausgaben sind, füge sie zusammen:

sort -m <(command1) <(command2) > outputfile

Oder führe beide Befehle gleichzeitig aus (könnte aber die Dinge ein wenig durcheinander bringen):

cat <(command1 & command2) > outputfile

Der Operator <() richtet eine benannte Pipe (oder / dev / fd) für jeden Befehl ein, leitet die Ausgabe dieses Befehls in die benannte Pipe (oder / dev / fd-Dateihandle-Referenz) und übergibt den Namen auf der Kommandozeile. Es gibt ein Äquivalent mit> (). Du könntest es tun: command0 | tee >(command1) >(command2) >(command3) | command4 um gleichzeitig die Ausgabe eines Befehls an 4 andere Befehle zu senden.


94
2017-08-16 18:28



genial! Ich habe die Manpage von Bash viel Zeit gelesen, aber ich habe diese nicht ausgewählt - Javier
Sie finden die Referenz in der [erweiterten Bash-Skript-Anleitung] (tldp.org/LDP/abs/html/process-sub.html) im Linux-Dokumentationsprojekt - brice
Du schaukelst. Vielen Dank. - Steve Kehlet
Ich war in der Lage, verschachtelte Zeilen zu verhindern grep --line-buffered - praktisch für gleichzeitig grep'in der tail von mehreren Protokolldateien. sehen stackoverflow.com/questions/10443704/line-buffered-cat - RubyTuesdayDONO


Sie können zwei Dämpfe an andere anschließen cat, wie Gorilla zeigt.

Sie können auch einen FIFO erstellen, die Ausgabe der Befehle an diesen richten und dann mit jedem anderen Programm aus dem FIFO lesen:

mkfifo ~/my_fifo
command1 > ~/my_fifo &
command2 > ~/my_fifo &
command3 < ~/my_fifo

Besonders nützlich für Programme, die nur eine Datei schreiben oder lesen, oder Programme, die nur stdout / file ausgeben, mit einer, die nur die andere unterstützt.


12
2017-08-16 17:43



Dieser funktioniert auf pfSense (FreeBSD), während die angenommene Antwort nicht funktioniert. Vielen Dank! - Nathan


(tail -f /tmp/p1 & tail -f /tmp/p2 ) | cat > /tmp/output

/tmp/p1 und /tmp/p2 sind deine Eingangsleitungen, während /tmp/output ist die Ausgabe.


8
2017-08-16 17:36



Hinweis: Es sei denn, beide Befehle in der Seite () Lege ihre Ausgabe auf jede Zeile (und einige andere obskure POSIX-Regeln für Atomizität), du könntest mit etwas merkwürdigem Scambling am Eingang zur Katze enden ... - freiheit
Sollten Sie kein Semikolon anstelle von kaufmännischem Und-Zeichen verwenden? - Samir


Ich habe dafür ein spezielles Programm erstellt: fdlinecombine

Es liest mehrere Pipes (normalerweise Programmausgaben) und schreibt sie zeilenweise nach stdout (Sie können das Trennzeichen auch überschreiben)


4
2017-07-26 00:09



Funktioniert wie angekündigt. Danke, dass Sie es veröffentlicht haben. - alexei


Ein wirklich cooler Befehl, den ich dafür benutzt habe, ist tpipeMöglicherweise müssen Sie kompilieren, weil es nicht so häufig ist. Es ist wirklich großartig, genau das zu tun, worüber du sprichst, und es ist so sauber, dass ich es normalerweise installiere. Die Manpage befindet sich hier http://linux.die.net/man/1/tpipe . Der aktuell gelistete Download befindet sich in diesem Archiv http://www.eurogaran.com/downloads/tpipe/ .

Es wird so benutzt,

## Reinject sub-pipeline stdout into standard output:
$ pipeline1 | tpipe "pipeline2" | pipeline3

3
2018-01-24 07:34





Sei vorsichtig hier; Wenn man sie nur katzt, werden die Ergebnisse schließlich auf eine Art und Weise gemischt, die man vielleicht nicht möchte: Zum Beispiel, wenn es sich um Log-Dateien handelt, möchte man wahrscheinlich keine Zeile von einer Zeile in die andere. Wenn das okay ist, dann

tail -f / tmp / p1 / tmp / p2>   / tmp / Ausgabe

wird funktionieren. Wenn das ist nicht Okay, dann musst du etwas finden, das Zeilenpufferung durchführt und nur komplette Zeilen ausgibt. Syslog macht das, aber ich bin mir nicht sicher, was sonst noch passieren könnte.

EDIT: Optimalisierung für ungepufferte Lese- und Named Pipes:

Betrachten von / tmp / p1, / ​​tmp / p2, / tmp / p3 als Named Pipes, erstellt von "mkfifo / tmp / pN"

tail -q -f / tmp / p1 / tmp / p2 | awk '{print $ 0> "/ tmp / p3"; schließen ("/ tmp / p3"); fflush ();} '&

Jetzt können wir auf diese Weise die Ausgabe named pipe "/ tmp / p3" lesen ungepuffert durch :

tail -f / tmp / p3

Es gibt einen kleinen Fehler der Art, Sie müssen die erste Eingabe-Pipe / tmp / p1 "initialisieren" durch:

echo -n> / tmp / p1

damit Schwanz wird zuerst die Eingabe von 2nd pipe / tmp / p2 akzeptieren und nicht warten bis etwas zu / tmp / p1 kommt. Dies ist möglicherweise nicht der Fall, wenn Sie sicher sind, erhält das / tmp / p1 zuerst die Eingabe.

Auch die Option -q wird benötigt, um Schwanz druckt keinen Müll über Dateinamen.


3
2017-08-16 17:45



desto nützlicher wird es sein: "tail -q -f / tmp / p1 / tmp / p2 | ein anderer Befehl" Wie es zeilenweise geschehen wird und mit der Option -q wird kein anderer Müll gedruckt - readyblue
für ungepufferte Datei / Named Pipe Verwendung: tail -q -f /tmp/p1 /tmp/p2 | awk '{print $0 > "/tmp/p3"; close("/tmp/p3"); fflush();}' &   jetzt kann das / tmp / p3 sogar benanntes Rohr sein und Sie können es einfach lesen tail -f /tmp/p3 all das ist UNBUFFERED = Zeile für Zeile  Es gibt jedoch einen kleinen Fehler der Art. Die 1. Datei / Named Pipe muss zuerst initialisiert werden, damit Tail die Ausgabe von der 2. akzeptiert. also wirst du müssen echo -n > /tmp/p1 und dann wird alles reibungslos funktionieren. - readyblue


Das beste Programm dafür ist lmerge. Im Gegensatz zu Freiharts Antwort ist es linienorientiert, so dass sich die Ausgabe der beiden Befehle nicht gegenseitig überlagert. Im Gegensatz zu anderen Lösungen führt es die Eingabe zusammen, sodass kein Befehl die Ausgabe dominieren kann. Zum Beispiel:

$ lmerge <(yes foo) <(yes bar) | head -n 4

Gibt die Ausgabe von:

foo
bar
foo
bar

0
2018-05-11 22:16