ich an einer Pipeline arbeite, die einige Verzweigungspunkte hat, die anschließend merge-- sie in etwa so aussehen:Wie kann ich STDOUT von mehreren Prozessen trennen und wieder verbinden?
command2
/ \
command1 command4
\ /
command3
Jeder Befehl an STDOUT schreibt und nimmt Eingaben über STDIN. STDOUT von command1 muss an command2 und command3 übergeben werden, die sequenziell ausgeführt werden, und ihre Ausgabe muss effektiv verkettet und an command4 übergeben werden. Ich dachte zunächst, dass so etwas wie dies funktionieren würde:
$ command1 | (command2; command3) | command4
Das allerdings nicht funktioniert, da nur STDOUT von command2 geben 4 zu befehlen, und wenn ich entfernen Command4 es offensichtlich ist, dass command3 nicht die geführt wird passender Stream von command1 - mit anderen Worten, es ist so, als ob command2 den Stream erschöpft oder verbraucht. Ich bekomme das gleiche Ergebnis mit {command2; Befehl3; } auch in der Mitte. Also dachte ich, ich sollte 'tee' with process substitution verwenden, und versucht, dies:
$ command1 | tee >(command2) | command3 | command4
Aber überraschend, dass auch nicht funktioniert - es scheint, dass der Ausgang des command1 und die Ausgabe von command2 in command3 geleitet werden, die führt zu Fehlern und nur die Ausgabe von Befehl3 wird in Befehl4 weitergeleitet. Ich fand, dass die folgende bekommt den entsprechenden Eingang und Ausgang zu und von command2 und command3:
$ command1 | tee >(command2) >(command3) | command4
jedoch strömt dies die Ausgabe von command1 auch Command4, was zu Problemen wie command2 führt und command3 eine anderes produziert Spezifikation als Befehl1. Die Lösung kam ich habe auf scheint hacky, aber es funktioniert:
$ command1 | tee >(command2) >(command3) > /dev/null | command4
Das command1 vorbei seine Ausgabe an Command4 unterdrückt, während STDOUT von command2 und command3 zu sammeln. Es funktioniert, aber ich habe das Gefühl, dass mir eine offensichtlichere Lösung fehlt. Bin ich? Ich habe Dutzende von Threads gelesen und habe keine Lösung für dieses Problem gefunden, das in meinem Anwendungsfall funktioniert, noch habe ich eine genaue Ausarbeitung des Problems des Teilens und erneuten Verbindens von Streams gesehen (obwohl ich nicht der erste sein kann) damit umzugehen). Sollte ich nur Named Pipes verwenden? Ich habe versucht, aber ich hatte Schwierigkeiten damit, das zu erreichen, also ist das vielleicht eine andere Geschichte für einen anderen Thread. Ich verwende bash in RHEL5.8.
Sieht so aus, als ob Ihre Frage eine Lösung hat - was funktioniert - fragen Sie nach einer anderen Lösung? Normalerweise wird diese Art der Aufteilung nicht häufig in Shell-Skripten angezeigt, aber häufig in speziellen Tools wie Hadoop-MapReduce - ich glaube nicht, dass Sie etwas besseres als Bash-Pipeline finden werden. – Soren
@Soren - Ja, ich frage mich, ob es eine bessere Lösung gibt. Ich habe keinen Schlaf verloren, da meine Lösung zu funktionieren scheint, aber ich erwarte, dass es eine Lösung gibt, die stdout nicht nach/dev/null umleitet und ich bin neugierig, wo ich mich geirrt habe, da es informativ sein könnte für mich (oder andere), während ich mich weiterentwickele. –