Könnten Sie die Handlung als Teil Ihrer Frage anders ausarbeiten ?
devnull
Sie haben aufgrund der internen Pufferung, die zum Implementieren der Pipe verwendet wird, und wie und geplant, nur begrenzte Kontrolle darüber, wie weit prog2die prog1Exits beim Beenden fortgeschritten sind. prog1prog2
Chepner
Schauen Sie sich auch [In welcher Reihenfolge werden Piped-Befehle ausgeführt?] (Unix.stackexchange.com/q/37508) an
DK Bose
Antworten:
4
Die allgemeine Antwort lautet nein. Es ist möglich prog2, vor dem prog1Start zu beenden (dies kann natürlich nicht passieren, wenn prog2tatsächlich eine Eingabe gelesen wird, was Sie erwarten würden, wenn Sie sie in einer Pipeline verwenden). Es ist definitiv möglich prog2, vorher zu beenden prog1; Dies ist beispielsweise prog2der Fall, wenn ein Suchprogramm beendet wird, sobald eine Übereinstimmung gefunden wird. In diesem Fall sind prog1möglicherweise noch nicht alle Daten vollständig erstellt.
Es gibt keine direkte Möglichkeit prog2, den Exit-Status von Exit abzurufen prog1oder gar zu wissen, dass es beendet prog1wurde. Alles was prog2man wissen kann ist, dass prog1es sein Rohrende geschlossen hat, was es tun kann, ohne zu sterben.
Wenn Sie den Exit-Status von prog1von erhalten möchten prog2, gibt es zwei gängige Methoden: Sie können ihn in eine Datei schreiben oder über die Pipe senden. Das Senden des Ausgabestatus als letzte Zeile der weitergeleiteten Daten ist möglich. Sie müssen sicherstellen, dass die letzte Zeile erst verarbeitet wird, wenn Sie wissen, dass es sich um die letzte Zeile handelt, dh bis Sie versucht haben, die nächste Zeile zu lesen.
{ prog1; echo $?;}|…
Hier ist ein Beispiel, in dem die rechte Seite ein Textfilter ist, der jede Zeile mit dem Wort „Fehler“ rot färbt. Wenn die linke Seite ausfällt, wird die rechte Seite mit demselben Status beendet.
{ prog1; echo $?;}| awk '
NR != 1 {
if (line ~ /[Ee][Rr][Rr][Oo][Rr]/) print "\033[31m" line "\033[0m";
else print line;
}
{line = $0}
END {exit($0)}
'
Ich habe versucht { command; echo ${PIPESTATUS[@]}; } | sort | ..., dass der Exit-Status im Stream an erster Stelle steht. Es ist alles sehr interessant!
@ illuminÉ Das würde nur funktionieren, wenn ${PIPESTATUS[@]}vor irgendetwas anderem in der Ausgabe von sortiert wird command. Wenn Sie commandeine Reihe von Zahlen ausdrucken oder beliebigen Text ausdrucken können, sind Sie in Schwierigkeiten: Sie können die Ausgabe nicht von der Statuszeile unterscheiden.
Gilles 'SO - hör auf böse zu sein'
Vielen Dank, tatsächlich gelingt es nur dann, einen Erfolgsstatus nach oben zu sortieren, wenn der Befehl keine 0 in seiner Ausgabe enthält lol. Tgif / s.
2
Obwohl Sie in einigen Sonderfällen (siehe die anderen Antworten) können, können Sie nicht in jedem Fall. Einige Filterprogramme werden einfach weiterlaufen, während andere die gesamte Ausgabe halten, sie in einem einzigen Druck auslösen und dann beenden.
Für ein Beispiel eines "einfach weitermachen" -Programms grepwird der Server wie gewohnt tail -f /var/log/some_log_file. Die Verwendung sortin einer Pipeline führt zu einem "Stillstand", da sortEingaben gesammelt werden, bis die vorgelagerte Pipe geschlossen wird. Die Verwendung xargsfügt eine weitere Komplikation hinzu: Werden die Programme von einem xargsTeil der Pipeline gestartet (es können viele Instanzen gestartet werden) oder nicht?
-1, weil Sie für die Rationalisierung einer falschen Antwort positiv bewertet wurden.
Strg-Alt-Delor
@richard Huh? Die Antwort von Bruce ist richtig (obwohl der zweite Absatz etwas verwirrend ist).
Gilles 'SO - hör auf böse zu sein'
1
Die Antwort: Nicht direkt.
@terdon hat gezeigt, dass der Exit-Code des vorherigen Befehls in der Pipe als expliziter Parameter an den nächsten Befehl gesendet werden muss.
Denken Sie daran, dass die Pipe lediglich eine Zuordnung des STDOUT des vorherigen Befehls zum STDIN des nächsten Befehls ist. Exit-Codes werden nicht an STDOUT (oder STDERR) ausgegeben.
-1, weil Sie dafür gestimmt haben, eine falsche Antwort zu zitieren und nicht viel mehr zu sagen.
Strg-Alt-Delor
@richard fair genug ... Ich hätte es noch einmal überprüfen sollen ... das ist passiert, wenn ich mich
zwinge,
1
Alle in der Pipeline befindlichen Prozesse werden vor jedem Beenden gestartet. Daher prog2könnte es erforderlich sein, diese Informationen nach dem Start abzurufen. Außerdem müsste die Verarbeitung prog1unterbrochen werden, bis sie beendet wurde. Dies könnte die Pipe blockieren. Es scheint grundlegende Probleme zu geben, das zu tun, was Sie verlangen, nicht Betriebssystembeschränkungen.
Sie müssen wahrscheinlich eine temporäre Datei in Betracht ziehen oder das Ergebnis in eine Variable einfügen.
Beispiel für eine kleine Datenmenge unter Verwendung einer Variablen.
tmp=$(prog1)if test "z$PIPESTATUS"=="z0"then…else…fi
Es gibt eine Lücke in Ihrer Argumentation. prog2wird prog1im Allgemeinen gestartet, bevor der Vorgang abgeschlossen ist. Es kann jedoch eine Möglichkeit geben, den Ausgabestatus prog1während der Ausführung zu erhalten.
prog2
dieprog1
Exits beim Beenden fortgeschritten sind.prog1
prog2
Antworten:
Die allgemeine Antwort lautet nein. Es ist möglich
prog2
, vor demprog1
Start zu beenden (dies kann natürlich nicht passieren, wennprog2
tatsächlich eine Eingabe gelesen wird, was Sie erwarten würden, wenn Sie sie in einer Pipeline verwenden). Es ist definitiv möglichprog2
, vorher zu beendenprog1
; Dies ist beispielsweiseprog2
der Fall, wenn ein Suchprogramm beendet wird, sobald eine Übereinstimmung gefunden wird. In diesem Fall sindprog1
möglicherweise noch nicht alle Daten vollständig erstellt.Es gibt keine direkte Möglichkeit
prog2
, den Exit-Status von Exit abzurufenprog1
oder gar zu wissen, dass es beendetprog1
wurde. Alles wasprog2
man wissen kann ist, dassprog1
es sein Rohrende geschlossen hat, was es tun kann, ohne zu sterben.Wenn Sie den Exit-Status von
prog1
von erhalten möchtenprog2
, gibt es zwei gängige Methoden: Sie können ihn in eine Datei schreiben oder über die Pipe senden. Das Senden des Ausgabestatus als letzte Zeile der weitergeleiteten Daten ist möglich. Sie müssen sicherstellen, dass die letzte Zeile erst verarbeitet wird, wenn Sie wissen, dass es sich um die letzte Zeile handelt, dh bis Sie versucht haben, die nächste Zeile zu lesen.Hier ist ein Beispiel, in dem die rechte Seite ein Textfilter ist, der jede Zeile mit dem Wort „Fehler“ rot färbt. Wenn die linke Seite ausfällt, wird die rechte Seite mit demselben Status beendet.
quelle
{ command; echo ${PIPESTATUS[@]}; } | sort | ...
, dass der Exit-Status im Stream an erster Stelle steht. Es ist alles sehr interessant!${PIPESTATUS[@]}
vor irgendetwas anderem in der Ausgabe von sortiert wirdcommand
. Wenn Siecommand
eine Reihe von Zahlen ausdrucken oder beliebigen Text ausdrucken können, sind Sie in Schwierigkeiten: Sie können die Ausgabe nicht von der Statuszeile unterscheiden.Obwohl Sie in einigen Sonderfällen (siehe die anderen Antworten) können, können Sie nicht in jedem Fall. Einige Filterprogramme werden einfach weiterlaufen, während andere die gesamte Ausgabe halten, sie in einem einzigen Druck auslösen und dann beenden.
Für ein Beispiel eines "einfach weitermachen" -Programms
grep
wird der Server wie gewohnttail -f /var/log/some_log_file
. Die Verwendungsort
in einer Pipeline führt zu einem "Stillstand", dasort
Eingaben gesammelt werden, bis die vorgelagerte Pipe geschlossen wird. Die Verwendungxargs
fügt eine weitere Komplikation hinzu: Werden die Programme von einemxargs
Teil der Pipeline gestartet (es können viele Instanzen gestartet werden) oder nicht?quelle
Die Antwort: Nicht direkt.
@terdon hat gezeigt, dass der Exit-Code des vorherigen Befehls in der Pipe als expliziter Parameter an den nächsten Befehl gesendet werden muss.
Denken Sie daran, dass die Pipe lediglich eine Zuordnung des STDOUT des vorherigen Befehls zum STDIN des nächsten Befehls ist. Exit-Codes werden nicht an STDOUT (oder STDERR) ausgegeben.
quelle
Alle in der Pipeline befindlichen Prozesse werden vor jedem Beenden gestartet. Daher
prog2
könnte es erforderlich sein, diese Informationen nach dem Start abzurufen. Außerdem müsste die Verarbeitungprog1
unterbrochen werden, bis sie beendet wurde. Dies könnte die Pipe blockieren. Es scheint grundlegende Probleme zu geben, das zu tun, was Sie verlangen, nicht Betriebssystembeschränkungen.Sie müssen wahrscheinlich eine temporäre Datei in Betracht ziehen oder das Ergebnis in eine Variable einfügen.
Beispiel für eine kleine Datenmenge unter Verwendung einer Variablen.
quelle
prog2
wirdprog1
im Allgemeinen gestartet, bevor der Vorgang abgeschlossen ist. Es kann jedoch eine Möglichkeit geben, den Ausgabestatusprog1
während der Ausführung zu erhalten.Um Gilles 'Antwort zu beenden ,
ist ein Ansatz.
prog2
könnte auch nicht/tmp/prog1.status
oder/tmp/prog1.status
regelmäßig, während Sie die Standardeingabe lesen.quelle