2012-03-02 15 views
5

Estoy escribiendo un script bash que genera una serie de procesos en segundo plano. Me gustaría recibir notificaciones cada vez que finalice un proceso; y me gustaría saber el pid del proceso terminado.pid de captura de proceso de fondo terminado utilizando trap en bash

He examinado usando wait, de manera que los PIDs de cada proceso generado se capturan y se almacenan en una matriz y, a continuación la matriz se repiten a lo largo, y esperar que se llama en cada proceso. Esta técnica se describe de varias maneras aquí:

https://stackoverflow.com/a/356154/366856

El problema con esto, si he entendido bien, es que puede ser relativamente ineficaz si desea realizar alguna acción tan pronto como un por concluido el proceso individuales . Por ejemplo, si generas los procesos A y B, y B termina antes de A, entonces la ejecución debe esperar a que terminen tanto A como B. Necesito realizar una acción tan pronto como B finalice.

Parece que trap SIGCHLD es la manera de realizar una acción inmediatamente cuando un niño termina, pero el problema es que no puedo encontrar una manera de determinar el pid de la fuente de la señal SIGCHLD, que también necesito. Lo más parecido que he encontrado a un ejemplo práctico de esto es el tercer ejemplo de código en este post:

http://www.linuxforums.org/forum/programming-scripting/103996-multithreading-bash.html#post510187

He copia-pegar aquí por conveniencia:

#!/bin/bash 

iNext=0 

function ChildReturned() { 
     wait $1 
     echo "$1 was returned. Its exits status was: $?" 
     iNext=$((iNext+1)) 
     StartChild $iNext 
} 


function StartChild { 
     ./child $1 & 
     pid=$! 
     echo "Started: $1 PID= $pid" 
     trap 'ChildReturned $pid' SIGCHLD 
} 


set -bm 

for ((iNext=0; iNext<=10; iNext++)); 
do 
     StartChild $iNext 
done 

wait 

I Creo que este ejemplo no funciona, porque el autor comete el error de llamar al trap varias veces, capturando cada vez una variable pid diferente en el argumento trap. Cada vez que se invoca una captura, sobrescribe la llamada anterior y, por lo tanto, se capturará un pid arbitrario. No he podido encontrar una mejor técnica.

¿Hay alguna forma de obtener el pid de un proceso secundario terminado utilizando trap in bash?

actualización

solo quería señalar a este recurso, que contiene la mejor visión general, más completa de soluciones a este problema que he visto hasta ahora:

http://mywiki.wooledge.org/ProcessManagement#I_want_to_process_a_bunch_of_files_in_parallel.2C_and_when_one_finishes.2C_I_want_to_start_the_next._And_I_want_to_make_sure_there_are_exactly_5_jobs_running_at_a_time.

+2

http://mywiki.wooledge.org/ProcessManagement – jordanm

+0

'kill -0 $ PID': ¡muy útil! ¡Gracias! – jbeard4

+0

Mejor aún, la sección llamada * Quiero procesar un grupo de archivos en paralelo, y cuando uno termina, quiero comenzar el siguiente. Y quiero asegurarme de que haya exactamente 5 trabajos a la vez. * Mejor respuesta que he leído hasta ahora – jbeard4

Respuesta

3

Establezca la trampa una vez, y en la trampa puede llamar al jobs -n para ver qué niños han terminado desde la última vez que lo comprobó. Tenga en cuenta que esto no le dice qué niño envió el SIGCHLD; considere el caso donde dos niños mueren antes de entrar a la trampa. En ese caso, solo entrarás en la trampa una vez, y es un punto discutible a qué señal del niño estás respondiendo en realidad. Tenga en cuenta que -n es una extensión bash, y es posible que prefiera usar jobs -l.

+0

Genial, no sabía sobre 'trabajos -n'.Creo que esto debería resolver mi problema, así que voy a marcar esta cuestión como resuelta. – jbeard4

Cuestiones relacionadas