Lo script Shell attende il comando in background


12

Sto scrivendo una sceneggiatura, ma c'è qualcosa di cui ho bisogno che non riesco a trovare un modo per farlo ...

Ho bisogno di fare un comando in background "command1 &" e poi da qualche parte nello script devo aspettare che finisca prima di eseguire command2. Fondamentalmente, ho bisogno di questo:

NOTA: ogni comando viene eseguito in una directory specifica! alla fine del ciclo while il mio comando1 ha creato 4 directory, dove in ognuna viene eseguito il processo specifico in modo che il totale del processo in esecuzione sia 4

a=1

while [$a -lt 4 ]

     . command1
   #Generates 1 Process  

     a= `export $a +1`
done

   #Wait until the 4 process end and then run the command2 

    . command2

Ho visto qualcosa su un waitcomando con il numero di processo pid, ma anche quello non ha funzionato.


Controlli command1? Puoi modificarlo in modo che restituisca i PID dei 4 processi?
— terdon

Sì! ce l'ho già :)
— Joao Macau,

Ho aggiornato la mia risposta di conseguenza. Dimmi se corrisponde alle tue aspettative.
— Laurent C.,

Questa Q è correlata a questa: unix.stackexchange.com/questions/100801/… . L'unica differenza è che è necessario ottenere il PID da un processo in background. È possibile utilizzare la $!variabile per ottenere questo, passandolo al waitcomando come ho mostrato lì. $!contiene l'ultimo PID in background, mentre $$contiene il PID dell'ultima esecuzione del processo.
— slm

3
OK, ora la tua sceneggiatura non ha alcun senso. Ci sono errori di sintassi e stranezze tutt'intorno. Potresti mostrarci la sceneggiatura attuale ? Perché stai provando i comandi? Perché non solo eseguirli?
— terdon

Risposte:


22

È possibile utilizzare il comando wait PIDper attendere la fine di un processo.

È inoltre possibile recuperare il PID dell'ultimo comando con $!

Nel tuo caso, qualcosa del genere funzionerebbe:

command1 & #run command1 in background
PID=$! #catch the last PID, here from command1
command2 #run command2 while command1 is running in background
wait $PID #wait for command1, in background, to end
command3 #execute once command1 ended

Dopo la modifica, poiché hai più PID e li conosci, puoi farlo:

command1 & #run command1 in background
PID1=xxxxx
PID2=yyyyy
PID3=xxyyy
PID4=yyxxx
command2 #run command2 while command1 is running in background
wait $PID1 $PID2 $PID3 $PID4 #wait for the four processes of command1, in background, to end
command3 #execute once command1 ended

Dopo la modifica, se si conosce il PID creato (xxxxx, yyyyy, xxyyy, yyxxx), è possibile utilizzare anche wait, con l'elenco dei PID da attendere (vedi man). Se non li conosci, forse li puoi riunire in command1 (che cos'è command1? Una tua sceneggiatura?)
— Laurent C.

Probabilmente è meglio assicurarsi che siano raggruppati correttamente in primo luogo. Vedi la mia risposta per avere un'idea di come potrebbe essere fatto.
— Mikeserv,

4

Il modo più pulito per farlo sarebbe ottenere il comamnd1ritorno dei PID dei processi avviati e utilizzarli waitsu ciascuno di essi, come suggerito dalla risposta di @ LaurentC .

Un altro approccio sarebbe qualcosa del genere:

## Create a log file
logfile=$(mktemp)

## Run your command and have it print into the log file
## when it's finsihed.
command1 && echo 1 > $logfile &

## Wait for it. The [ ! -s $logfile ] is true while the file is 
## empty. The -s means "check that the file is NOT empty" so ! -s
## means the opposite, check that the file IS empty. So, since
## the command above will print into the file as soon as it's finished
## this loop will run as long as  the previous command si runnning.
while [ ! -s $logfile ]; do sleep 1; done

## continue
command2

scusa ma ancora non funziona .. Migliorerò ancora una volta la mia domanda!
— Joao Macau,

0

Se si utilizza il metodo seguente, potrebbe non essere necessario uno speciale "attendere tutti i processi" dopo il ciclo while. Il loop attenderà il command1completamento della corrente prima di tornare all'inizio. Si prega di prestare attenzione come per qualsiasi consiglio. Nota, l'unica cosa che ho fatto è stata aggiungere & wait $!alla fine del tuo command1.

a=1
while [$a -lt 4 ]
     . command1  & wait $!
   #Generates 1 Process  
     a= `export $a +1`
done
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.