Angenommen, ich habe die folgende Pipe:
a | b | c | d
Wie kann ich auf den Abschluss von c
(oder b
) in sh
oder warten bash
? Dies bedeutet, dass das Skript d
jederzeit gestartet werden kann (und nicht gewartet werden muss), jedoch eine vollständige Ausgabe von benötigt c
, um ordnungsgemäß zu funktionieren.
Der Anwendungsfall ist ein difftool
für git
den Vergleich von Bildern. Es wird von aufgerufen git
und muss seine Eingabe (das a | b | c
Teil) verarbeiten und die Ergebnisse des Vergleichs (das d
Teil) anzeigen . Der Anrufer löscht die für a
und erforderlichen Eingaben b
. Dies bedeutet, dass der Prozess c
(oder b
) beendet werden muss , bevor Sie vom Skript zurückkehren . Andererseits kann ich nicht warten, d
da dies bedeutet, dass ich auf Benutzereingaben warte.
Ich weiß, dass ich die Ergebnisse c
in eine temporäre Datei schreiben oder vielleicht ein FIFO verwenden kann bash
. (Sie sind sich jedoch nicht sicher, ob das FIFO helfen wird.) Ist dies ohne temporäre Dateien möglich sh
?
BEARBEITEN
Vielleicht würde es ausreichen, wenn ich die Prozess-ID des c
(oder b
) Prozesses zuverlässig herausfinden könnte . Dann könnte die gesamte Pipe asynchron gestartet werden und ich könnte auf eine Prozess-ID warten. Etwas in der Art von
wait $(a | b | { c & [print PID of c] ; } | d)
EDIT ^ 2
Ich habe eine Lösung gefunden, Kommentare (oder noch bessere Lösungen) sind willkommen.
d
diec
Ausgabe erst nachc
Abschluss der Verarbeitung starten ? Sie möchten nichtd
jede Ausgabezeile sofort verarbeiten?d
beginnen,c
muss aber beendet werden, bevor ich weitermachen kann.d
anfangen können, wann es Ihnen gefällt, worauf warten Sie dann genau?d
die Ausgabe von nicht verwendet wirdc
, scheint es keinen Sinn zu machen,d
Teil der Pipeline zu sein. Wennd
die Eingabe jedoch verwendet wird,d
muss eine Weile an der Eingabe gearbeitet werden, nachdem Sie alles gelesen haben, damit Ihr Ansatz einen Unterschied macht.Antworten:
Die Benachrichtigung kann zB durch ein Signal an eine PID erfolgen, die in einer Umgebungsvariablen (
kill -USR1 $EXTPID
) übergeben wurde, oder durch Erstellen einer Datei (touch /path/to/file
).Eine andere Idee:
Sie führen den nächsten Prozess (den, auf den Sie warten können) aus der Pipeline aus:
oder
quelle
notify
könnte ausgeführt werden, bevor ich die Signalfalle einrichte. Wie kann ich sicherstellen, dass dieses Signal nicht verpasst wird?trap
definiert wurde.{ c; bg; }
oder{ c; exit 0; }
scheint nicht zu funktionieren.Wenn ich Ihre Frage richtig verstehe, sollte dies funktionieren:
(Der fd 3-Trick ist, weil einige (die meisten) Shells stdin mit / dev / null umleiten
&
).quelle
In bash können Sie eine Prozessersetzung verwenden . Der Befehl in der Prozessersetzung wird asynchron ausgeführt und nicht gewartet.
quelle
bash
nur richtig - keinesh
Unterstützung?Dies ist, was ich durch Versuch und Irrtum mit Hilfe von Haukes Input gefunden habe:
Gleichwertig:
(Letzteres ist expliziter, da
{}
es ohnehin in einer Unterschale ausgeführt wird, wenn es sich in einem Rohr befindet.)Einige andere Signale (einschließlich
QUIT
,TERM
undUSR1
) auch funktioniert jedoch in diesem Fall die Beschreibung des Signals wird auf dem Terminal angezeigt.Ich frage mich, ob dies die ursprüngliche Absicht des
PIPE
Signals ist. Nach dem Handbuch :Dies bedeutet, dass wenn ich ein Pipe-Signal künstlich an die Subshell sende, es stillschweigend endet und der Endverbraucher (
d
) in Ruhe lässt.Dies funktioniert sowohl in
sh
als auchbash
.quelle
Sie können das
sponge
Programm aus dem Paket "moreutils" verwenden:a | b | c | sponge | d
Schwamm wird für das Ende der
c
Ausgabe vor dem Weiterleiten and
. Hoffe das ist was du wolltest.quelle
Sie können einfach tun:
Wenn der
d
Vorgang abgeschlossen ist,cat
wird der Rest derc
Ausgabe absorbiert, bis der Vorgang abgeschlossen ist.In Ordnung. Nach Kommentaren denke ich, dass die Antwort darin besteht, direkt
d
im Hintergrund zu beginnen.Tun:
oder verwenden Sie die Lösung von Stephane Chazelas , wenn Probleme beim
d
Lesen von stdin auftreten .quelle
c
endet früher alsd
und ich muss warten, bis erc
fertig ist, aber es ist mir egald
.c
Vorgang abgeschlossen ist undd
noch ausgeführt wird? Tötend
?d
hat eine GUI und kann ausgeführt werden, bis der Benutzer sie schließt.a
,b
undc
ihre Arbeit beenden, schließen sie stdout und verlassen; undd
läuft nur noch. Möchten Sie nach Abschluss des Vorgangsd
in den Hintergrund sendenc
? Ist es das?d
sollte nach Abschluss in den Hintergrund gesendet werdenc
.