Quali comandi dovrei usare per creare due processi secondari in serie?


8

Voglio generare due processi figlio, ma aspetto che il primo raggiunga un certo punto della sua esecuzione (che può essere determinato esaminando lo stdout) prima di generare il secondo. Non sono sicuro di quali comandi unix sarebbero coinvolti nella realizzazione di questo, e ho avuto difficoltà a trovare qualcosa tramite Google a causa della natura concisa e talvolta criptica dei nomi dei comandi unix.

Non sto cercando una soluzione al problema specifico che sto tentando di risolvere (anche se ogni puntatore aggiuntivo sarebbe apprezzato), mi occupo principalmente di sapere quali comandi unix vorrei cercare e imparare a usare.


Sei aperto all'utilizzo di Python?
xrisk,

3
Senza sapere come si determina il "certo punto nella sua esecuzione", questo è molto vago.
Muru,

@muru modificato per chiarire
w.brian,

Quindi in realtà hai bisogno di 3 processi. 1. corre, creando output; 2. monitora l'output di 1, e a un certo punto inizia 3. Queste sono informazioni sufficienti per iniziare a creare qualunque cosa tu stia facendo. Ma non è un buon modo di progettare un programma.
djsmiley2kStaysInside

Risposte:


7

È possibile utilizzare l' xargsutilità per questo. Può eseguire un comando per ogni riga su stdin, quindi dobbiamo solo assicurarci che xargsottenga come input una singola riga su stdin nel momento in cui dovrebbe iniziare il comando, che può essere realizzato con grep:

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

Gli argomenti --max-count=1, --max-lines=1e --no-run-if-emptyassicurano che proc2viene avviato esattamente una volta se e quando proc1uscite ${targetString}per la prima volta, e mai se proc1mai uscite ${targetString}. Le --replaceevita che xargsaggiunge la linea di ingresso alla sua linea di comando.

Ho usato la seguente riga di comando per testarlo:

(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"

1
+1 Questa è una risposta molto creativa. Sarebbe molto più complicato se avessi bisogno del resto dell'output di proc1. Dovresti usare cose come tee e descrittori di file aggiuntivi o named pipe.
Joe,

7

Non sono sicuro che ci sia un comando / risposta elegante alla domanda che hai posto (cioè raggiungere un certo punto nella sua esecuzione) - ma ci sono strumenti / tecniche che possono essere usati per aggirare una soluzione, probabilmente coinvolgendo più di 1 di quanto segue e forse altre cose che non conosco ancora:

  1. Processi di background (&)
  2. Esecuzione condizionale (&& e ||)
  3. dormire
  4. aspetta (mi aspetto che ciò sia particolarmente utile - se avvii più di 1 lavoro in background, attenderà il completamento di tutti i lavori)
  5. Named pipe (che potrebbero fornire un meccanismo per parlare tra i processi).
  6. inodenotifywait

Scrivere e controllare i file di blocco è anche pratica comune (suggerimento pro - se hai il controllo dell'ambiente, scrivi sul ramdisk anziché / tmp - su molte distro questo è / dev / shm).


6

Questa è solo un'idea, ma fai in modo che il primo processo installi il suo output in grep. Fai in modo che grep pipe il suo output in un loop di riga di lettura e confronta ogni riga con ciò che stai cercando. Una volta trovato, esegui proc2.

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

Se "un certo punto della sua esecuzione" può essere determinato da stdout, allora che ne dici di quanto segue?

proc1 | grep "stdout trigger string" && proc2

&&dovrebbe sparare quando grepritorna 0, cosa che fa solo quando trova una corrispondenza.


1
grep continuerà fino a quando stdin sarà chiuso. Fino a quel momento non restituirà nulla (0 o altro).
Bob,

@Bob Oh, grazie ... Proverò a riformulare questa idea.
Louis Waweru,

@bob Sarebbe particolarmente disordinato e disgiunto, e un uso improprio dello strumento, ma potresti usare fail2ban per monitorare un file di registro (cioè pipe stdout in un file), e quindi programmare una regola per eseguire il secondo script quando quella linea è trovato (ma riconosco la modifica di un file trigger e l'utilizzo di inotify è una soluzione più elegante)
davidgo,

1
Se targettring si verifica più di una volta nell'output proc1, proc2 verrà eseguito più volte. Se lo facessi proc2 &e poi break, ciò non accadrà, ma ciò chiuderebbe il tubo e farebbe terminare prematuramente proc1. In alternativa, è possibile impostare un flag una volta avviato proc2 e utilizzarlo per assicurarsi che proc2 non venga eseguito nuovamente. Come con l'altra risposta, il resto dell'output proc1 viene scartato, quindi se ne hai bisogno, è necessario più lavoro.
Joe,

1
@Joe buon punto. La domanda originale era in realtà solo chiedersi quali fossero i comandi disponibili con cui lavorare, quindi questa è davvero solo una risposta che dimostra alcune delle potenzialità di quei comandi (principalmente |e grepqui).
Louis Waweru,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.