2012-02-13 8 views
29

Ho bisogno di uno script bash che esegue le seguenti operazioni:Come posso ottenere sia l'ID di processo che il codice di uscita da uno script di bash?

  • avvia un processo di fondo con tutto l'output diretto a un file
  • Scrive codice di uscita del processo in un file
  • Restituisce il pid del processo (subito , non quando il processo termina).
  • Lo script deve uscire

posso ottenere il PID, ma non il codice di uscita:

$ executable >>$log 2>&1 & 
pid=`jobs -p` 

Oppure, posso catturare il codice di uscita, ma non il pid:

$ executable >>$log; 
# blocked on previous line until process exits 
echo $0 >>$log; 

Come posso fare tutti questi allo stesso tempo?

risposta

53

Il pid è in $!, non è necessario eseguire jobs. E lo stato di ritorno viene restituito dal wait:

$executable >> $log 2>&1 & 
pid=$! 
wait $! 
echo $? # return status of $executable 

EDIT 1

Se ho ben capito il requisito aggiuntivo, come indicato in un commento, e si desidera che lo script per tornare subito (senza attendere il comando per finire), quindi non sarà possibile avere lo script iniziale scrivere lo stato di uscita del comando. Ma è abbastanza facile che un intermediario scriva lo stato di uscita non appena il bambino finisce. Qualcosa di simile:

sh -c "$executable"' & echo pid=$! > pidfile; wait $!; echo $? > exit-status' & 

dovrebbe funzionare.

EDIT 2

Come sottolineato nei commenti, questa soluzione ha una condizione di competizione: lo script principale termina prima che il pidfile è scritto. L'OP risolve questo facendo un ciclo di sonno elettorale, che è un abominio e temo che avrò problemi a dormire di notte sapendo che potrei aver motivato una simile parodia. IMO, la cosa giusta da fare è aspettare fino a quando il bambino ha finito. Dal momento che è inaccettabile, ecco una soluzione che blocca su una lettura fino a quando esiste il file pid invece di fare il sonno loop:

{ sh -c "$executable > $log 2>&1 &"' 
echo $! > pidfile 
echo # Alert parent that the pidfile has been written 
wait $! 
echo $? > exit-status 
' & } | read 
+0

Grazie mille. Questo è abbastanza vicino. Temo di aver omesso un altro requisito. Lo script di bash deve finire. Se eseguo "wait $ pid; echo $? >> $ log" in uno script helper in background, otterrò un errore "not a child". –

+2

Se si desidera che lo script termini prima che il bambino finisca, non è possibile scrivere il codice di uscita del figlio senza richiamare un'anomalia temporale di qualche tipo. –

+0

Avvolgi l'intero 'sh -c" ($ eseguibile "'... exit-status)' &' nelle parentesi sub-shell. Ciò consente alla subshell di andare avanti con la sua vita mentre il genitore va avanti con tutto ciò che deve fare. Potresti voler aggiungere un altro '&' dopo ')'. –

Problemi correlati