Jakich poleceń użyłbym do utworzenia dwóch procesów potomnych szeregowo?

8

Chcę odrodzić dwa procesy potomne, ale przed odrodzeniem drugiego poczekaj, aż pierwszy osiągnie określony punkt w jego wykonaniu (który można ustalić, badając standardowe wyjście). Nie jestem pewien, które komendy uniksowe byłyby zaangażowane w osiągnięcie tego, i miałem trudności ze znalezieniem czegokolwiek za pośrednictwem google ze względu na zwięzłą, a czasem tajemniczą naturę nazw komend unix.

Nie szukam rozwiązania konkretnego problemu, który próbuję rozwiązać (chociaż dodatkowe wskaźniki byłyby mile widziane), przede wszystkim martwię się o to, które polecenia unixowe chciałbym wyszukać i nauczyć się używać.

w.brian
źródło
Czy jesteś otwarty na używanie Pythona?
xrisk
3
Nie wiedząc, w jaki sposób określasz „określony moment jego wykonania”, jest to bardzo niejasne.
muru
@muru zredagowano w celu wyjaśnienia
w.brian
Tak naprawdę potrzebujesz 3 procesów. 1. działa, tworząc dane wyjściowe; 2. monitoruje wyjście 1 i w pewnym momencie zaczyna się 3. To wystarczająca ilość informacji, aby zacząć robić to, co robisz. Ale to nie jest dobry sposób na zaprojektowanie programu.
djsmiley2kStaysInside

Odpowiedzi:

7

Możesz do tego użyć xargsnarzędzia. Może uruchomić polecenie dla każdego wiersza na standardowym xargswejściu , więc musimy tylko upewnić się, że pobiera on jako wejście pojedynczy wiersz na standardowym wejściu w czasie, gdy powinien uruchomić polecenie, co można osiągnąć za pomocą grep:

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

Argumenty --max-count=1, --max-lines=1i --no-run-if-emptyzapewniają, że proc2rozpoczyna się dokładnie raz, czy i kiedy proc1wyjść ${targetString}po raz pierwszy, i nigdy, jeśli proc1nigdy nie stosowały wyjść ${targetString}. W --replaceUnika że xargsDołącza linię wejściową do swojej linii komend.

Użyłem następującego wiersza polecenia, aby go przetestować:

(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
źródło
1
+1 To jest bardzo kreatywna odpowiedź. Byłoby to znacznie bardziej skomplikowane, gdybyś potrzebował reszty danych wyjściowych z proc1. Musisz użyć takich rzeczy jak tee i dodatkowe deskryptory plików lub nazwane potoki.
Joe
7

Nie jestem pewien, czy istnieje eleganckie polecenie / odpowiedź na zadane pytanie (tj. Osiągnięcie określonego punktu w jego wykonaniu) - ale istnieją narzędzia / techniki, których można użyć do rozwiązania problemu, prawdopodobnie obejmującego więcej niż 1 następujące, a może inne rzeczy, o których jeszcze nie wiem:

  1. Procesy w tle (i)
  2. Warunkowe wykonanie (&& i ||)
  3. sen
  4. czekaj (spodziewam się, że będzie to szczególnie przydatne - jeśli uruchomisz więcej niż 1 zadanie w tle, poczeka, aż wszystkie zadania zostaną ukończone)
  5. Nazwane potoki (które mogłyby zapewnić mechanizm do rozmowy między procesami).
  6. inodenotifywait

Pisanie i sprawdzanie plików blokujących jest również powszechną praktyką (wskazówka - jeśli masz kontrolę nad środowiskiem, pisz na ramdysku zamiast / tmp - w wielu dystrybucjach jest to / dev / shm).

Davidgo
źródło
6

To tylko pomysł, ale pierwszy proces potokowy powinien wyprowadzać dane wyjściowe do grep. Niech grep potoczy wyjście do pętli linii odczytu i porównaj każdą linię z tym, czego szukasz. Po znalezieniu uruchom proc2.

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

Jeśli „określony punkt w jego wykonaniu” może zostać określony stdout, to co z tego?

proc1 | grep "stdout trigger string" && proc2

&&powinien strzelać po greppowrocie 0, co robi tylko wtedy, gdy znajdzie dopasowanie.

Louis Waweru
źródło
1
grep będzie działał do momentu zamknięcia standardowego wejścia. Do tego czasu nic nie zwróci (0 lub inaczej).
Bob
@ Bob Och, dziękuję ... Spróbuję przeformułować ten pomysł.
Louis Waweru
@bob Byłoby to szczególnie niechlujne i rozłączne, a także niewłaściwe użycie narzędzia, ale można użyć fail2ban do monitorowania pliku dziennika (tj. stdout potoku do pliku), a następnie zaprogramować regułę wykonywania drugiego skryptu, gdy wiersz ten jest znaleziono (ale ponownie modyfikuję plik wyzwalacza i użycie inotify jest bardziej eleganckim rozwiązaniem)
davidgo
1
Jeśli ciąg docelowy występuje więcej niż jeden raz w wyniku wyjściowym proc1, proc2 zostanie uruchomiony wiele razy. Jeśli tak proc2 &, a następnie break, że nie stało, ale to by zamknąć przewód i dokonać PROC1 zakończyć przedwcześnie. Alternatywnie, możesz ustawić flagę po uruchomieniu proc2 i użyć jej, aby upewnić się, że proc2 nie uruchomi się ponownie. Podobnie jak w przypadku innej odpowiedzi, reszta danych wyjściowych proc1 jest odrzucana, więc jeśli jej potrzebujesz, potrzeba więcej pracy.
Joe
1
@Joe Dobra uwaga. Oryginalny pytanie zostało faktycznie tylko z prośbą o to, co było dostępne do pracy z polecenia, więc jest to naprawdę tylko odpowiedź wykazując pewne potencjału tych poleceń (głównie |i greptutaj).
Louis Waweru