Come ottenere un elenco di tutti i processi figlio generati da uno script


9

Contesto:

Gli utenti mi forniscono i loro script personalizzati per l'esecuzione. Questi script possono essere di qualsiasi tipo come gli script per avviare più programmi GUI, servizi di back-end. Non ho controllo su come sono scritti gli script. Questi script possono essere di tipo bloccante, ovvero l'esecuzione attende fino all'uscita di tutti i processi figlio (programmi eseguiti in sequenza)

#exaple of blocking script
echo "START"
first_program 
second_program 
echo "DONE"

o di tipo non bloccante, ad esempio quelli che fork il processo figlio in background ed escono qualcosa del genere

#example of non-blocking script
echo "START"
first_program &
second_program &
echo "DONE"

Cosa sto cercando di ottenere?

Gli script forniti dall'utente possono essere di uno qualsiasi dei due tipi sopra elencati o entrambi. Il mio compito è quello di eseguire lo script e attendere fino a quando tutti i processi avviati da esso terminano e quindi arrestano il nodo. Se è di tipo bloccante, case è semplicemente semplice, vale a dire ottenere il PID del processo di esecuzione dello script e attendere fino a ps -ef | grep -ef Il PID non ha più voci. Gli script non bloccanti sono quelli che mi danno problemi

Esiste un modo per ottenere l'elenco dei PID di tutto il processo figlio generato dall'esecuzione di uno script? Eventuali suggerimenti o suggerimenti saranno molto apprezzati


Non credo che sia possibile dopo la fine dello script genitore, a meno che non sia possibile acquisire il PID del genitore. Se stai lanciando gli script, potresti racchiuderli in qualcosa del genere pid$(foo.sh; echo $!)che ti darà il PID in foo.shmodo da poterlo usare ps --ppid. Funzionerà?
terdon,

2
Gli script devono essere eseguiti sotto l'UID dell'utente autore? In caso contrario, puoi creare un utente fittizio solo per questo scopo? Non avresti nemmeno bisogno grep, solo ps –udummy_user. Inoltre, guarda i gruppi di processi.
Scott,

Questo è più un tipo di soluzione alternativa che una soluzione per la tua domanda iniziale: Apri una nuova sessione bash. Puoi elencare tutti i processi generati da questa shell usando pssenza alcun argomento (dovrebbe essere solo bashe psall'inizio). Inizia la tua sceneggiatura lì. Al termine, attendere fino a ps | wc -lraggiungere il valore previsto.
Tim

Risposte:


8

Per rispondere direttamente alla tua domanda, il comando

jobs -p

ti dà l'elenco di tutti i processi figlio.

Alternativa n. 1

Ma nel tuo caso potrebbe essere più semplice usare il comando waitsenza parametri:

first_program &
second_program &
wait

Questo attenderà il completamento di TUTTI i processi figlio.

Alternativa n. 2

Un'altra alternativa sta usando $!per ottenere il PID dell'ultimo programma e forse accumularsi in una variabile, in questo modo:

pids=""
first_program &
pids="$pids $!"
second_program &
pids="$pids $!"

e quindi usa wait con quello (questo è nel caso in cui tu voglia aspettare solo un sottoinsieme dei tuoi processi figlio):

wait $pids

Alternativa n. 3

OPPURE, se si desidera attendere solo fino al termine di QUALSIASI processo, è possibile utilizzare

wait -n $pids

Informazioni sul bonus

Se vuoi che un sigterm al tuo script bash chiuda anche i tuoi processi figlio, dovrai propagare il segnale con qualcosa del genere (mettilo da qualche parte in alto, prima di iniziare qualsiasi processo):

trap 'kill $(jobs -p)' SIGINT SIGTERM EXIT

1

Grazie ragazzi per le vostre risposte .. Ho ottenuto la soluzione su StackOverflow

È possibile utilizzare wait per attendere il completamento di tutti i processi in background avviati da userscript. Poiché wait funziona solo sui figli della shell corrente, dovrai procurartene lo script invece di eseguirlo come processo separato.

(fonte utenti; attesa)

Il sourcing dello script in una subshell esplicita dovrebbe simulare l'avvio di un nuovo processo abbastanza da vicino. In caso contrario, è anche possibile eseguire lo sfondo della subshell, che forza l'avvio di un nuovo processo, quindi attendere il completamento.

(fonte userscript; wait) & wait

Ecco il link per la risposta originale di @chepner: /programming/18663196/how-to-get-list-of-all-child-process-spawned-by-a-script/18663969?noredirect = 1 # 18.663.969


3
Ho pensato anche a questo, ma questa soluzione fallisce quando userscript avvia un pedice in background che quindi avvia un altro script in background. Il tuo waitcomando attenderà quindi i figli di userscript ma non i suoi nipoti.
Tim

@Tim Ho appena capito che :(
irraju,
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.