Mit welchen Befehlen würde ich zwei untergeordnete Prozesse seriell erstellen?

8

Ich möchte zwei untergeordnete Prozesse erzeugen, aber warten Sie, bis der erste einen bestimmten Punkt in seiner Ausführung erreicht (der durch Untersuchen von stdout bestimmt werden kann), bevor Sie den zweiten erzeugen. Ich bin mir nicht sicher, welche Unix-Befehle dazu beitragen würden, und es fiel mir schwer, über Google etwas zu finden, da Unix-Befehlsnamen knapp und manchmal kryptisch sind.

Ich suche keine Lösung für das spezifische Problem, das ich zu lösen versuche (obwohl zusätzliche Hinweise erwünscht wären). Ich möchte in erster Linie wissen, welche Unix-Befehle ich nachschlagen und deren Verwendung lernen möchte.

w.brian
quelle
Sind Sie offen für Python?
Xrisk
3
Ohne zu wissen, wie Sie den "bestimmten Punkt in seiner Ausführung" bestimmen, ist dies sehr vage.
Muru
@ Guru bearbeitet, um zu klären
w.brian
Sie benötigen also tatsächlich 3 Prozesse. 1. läuft, erstellt Ausgabe; 2. überwacht die Ausgabe von 1 und startet an einem bestimmten Punkt 3. Dies sind genug Informationen, um damit zu beginnen, was auch immer Sie machen. Aber es ist keine gute Möglichkeit, ein Programm zu entwerfen.
djsmiley2kStaysInside

Antworten:

7

Sie können das xargsDienstprogramm dafür verwenden. Es kann einen Befehl für jede Zeile in stdin ausführen, daher müssen wir nur sicherstellen, dass xargszum Zeitpunkt des Starts des Befehls eine einzelne Zeile in stdin als Eingabe abgerufen wird. Dies kann ausgeführt werden mit grep:

proc1 | grep --max-count=1 "${targetString}" | xargs --max-lines=1 --no-run-if-empty --replace -- proc2

Die Argumente --max-count=1, --max-lines=1und stellen Sie --no-run-if-emptysicher, dass proc2genau einmal gestartet wird, wenn und wann zum ersten Mal proc1ausgegeben ${targetString}wird, und nie, wenn proc1nie ausgegeben wird ${targetString}. Das --replacevermeidet, dass xargsdie Eingabezeile an ihre Befehlszeile angehängt wird.

Ich habe die folgende Befehlszeile verwendet, um es zu testen:

(echo Start >&2; sleep 3 ; echo Trigger; sleep 3; echo End >&2) | grep --max-count=1 Trigger | xargs --max-lines=1 --no-run-if-empty --replace -- echo "Triggered"
Philipp Wendler
quelle
1
+1 Dies ist eine sehr kreative Antwort. Es würde jedoch erheblich komplizierter werden, wenn Sie den Rest der Ausgabe von proc1 benötigen. Sie müssten Dinge wie Tee und zusätzliche Dateideskriptoren oder Named Pipes verwenden.
Joe
7

Ich bin mir nicht sicher, ob es einen eleganten Befehl / eine elegante Antwort auf die von Ihnen gestellte Frage gibt (dh einen bestimmten Punkt in der Ausführung erreichen) - aber es gibt Tools / Techniken, mit denen eine Lösung gefunden werden kann, an der wahrscheinlich mehr als eine beteiligt ist Folgendes und vielleicht andere Dinge, von denen ich noch nichts weiß:

  1. Hintergrundprozesse (&)
  2. Bedingte Ausführung (&& und ||)
  3. Schlaf
  4. Warten (Ich gehe davon aus, dass dies besonders nützlich sein wird. Wenn Sie mehr als einen Job im Hintergrund starten, wird gewartet, bis alle Jobs abgeschlossen sind.)
  5. Named Pipes (die einen Mechanismus zum Sprechen zwischen Prozessen bieten könnten).
  6. inodenotifywait

Das Schreiben und Überprüfen von Sperrdateien ist ebenfalls gängige Praxis (Tipp: Wenn Sie die Kontrolle über die Umgebung haben, schreiben Sie auf die Ramdisk anstatt auf / tmp - in vielen Distributionen ist dies / dev / shm).

Davidgo
quelle
6

Dies ist nur eine Idee, aber der erste Prozess leitet seine Ausgabe an grep weiter. Lassen Sie die Ausgabe von grep an eine gelesene Zeilenschleife weiterleiten und vergleichen Sie jede Zeile mit dem, was Sie suchen. Sobald gefunden, führen Sie proc2 aus.

#!/bin/bash
targetString="line you are looking for"
proc1 | grep "${targetString}" |
while read line
do
if [ "$line" = "${targetString}" ]; then
    proc2
fi
done

Wenn "ein bestimmter Punkt in seiner Ausführung" durch bestimmt werden kann stdout, wie wäre es dann mit dem Folgenden?

proc1 | grep "stdout trigger string" && proc2

&&sollte bei der grepRückkehr ausgelöst werden 0, was nur dann der Fall ist, wenn eine Übereinstimmung gefunden wird.

Louis Waweru
quelle
1
grep wird so lange weitermachen, bis stdin geschlossen ist. Bis dahin wird nichts (0 oder anders) zurückgegeben.
Bob
@ Bob Oh, danke ... Ich werde versuchen, diese Idee neu zu formulieren.
Louis Waweru
@bob Es wäre besonders chaotisch und unzusammenhängend und ein Missbrauch des Tools, aber Sie könnten fail2ban verwenden, um eine Protokolldatei zu überwachen (dh Pipe stdout zu einer Datei) und dann eine Regel zu programmieren, um das zweite Skript auszuführen, wenn diese Zeile ist gefunden (aber ich rekonstruiere das Ändern einer
Triggerdatei
1
Wenn die Zielzeichenfolge in der Ausgabe von proc1 mehrmals vorkommt, wird proc2 mehrmals ausgeführt. Wenn ja , proc2 &und dann breakwäre das nicht passieren, aber das würde das Rohr und macht proc1 vorzeitig beenden schließen. Alternativ können Sie nach dem Start von proc2 ein Flag setzen und damit sicherstellen, dass proc2 nicht erneut ausgeführt wird. Wie bei der anderen Antwort wird der Rest der proc1-Ausgabe verworfen. Wenn Sie ihn benötigen, ist mehr Arbeit erforderlich.
Joe
1
@ Joe Guter Punkt. Die ursprüngliche Frage war eigentlich nur die Frage, mit welchen Befehlen gearbeitet werden konnte. Dies ist also nur eine Antwort, die einige der Potenziale dieser Befehle (hauptsächlich |und grephier) demonstriert .
Louis Waweru