2010-03-26 20 views
20

Tengo una colección de scripts controlados por uno principal. Quiero atrapar la señal ctrl + c en el script principal y propagarlo a los demás. Las otras secuencias de comandos también deberían atrapar esta señal (del script principal) y hacer algunas tareas de limpieza ...¿Cómo propagar una señal a través de una colección de scripts?

He intentado enviar kill -s SIGINT a los niños, pero parece que no pueden captar la señal (incluso si se está definiendo trap 'Cleanup' SIGINT en los scripts secundarios)

¿Alguna pista sobre cómo realizar esto?

+1

Sería útil si muestra ejemplos específicos de un padre y un hijo abreviados. –

+0

Consulte mi respuesta en su otra pregunta para una posible solución. http://stackoverflow.com/questions/2524937/how-to-send-a-signal-sigint-from-script-to-script-bash –

Respuesta

-1

No estoy seguro de qué quiere decir con "otros scripts deberían atrapar esta señal del script principal"? ¿Cómo puede un script de subproceso usar código en el script principal para atrapar una señal?

No quiero intentar escribir mucho código para usted porque tampoco sé exactamente lo que quiere decir con "scripts controlados por uno principal", pero presumiblemente puede iniciar algunos subprocesos y luego tiene un bucle de control que comprueba si los otros scripts han salido y puede capturar su estado de salida? Si ese es el caso, lo que tiene más sentido para mí es que cada script haga su propia captura y limpieza. Cuando el script principal atrapa una señal, puede, si lo desea, pasar la señal a todos los niños (a través del kill -s <signal> pid). Cuando un proceso secundario atrapa una señal, puede devolver un estado de salida que indica que fue cancelada por esa señal. El principal puede manejar ese estado de salida adecuadamente, tal vez de la misma manera que si hubiera recibido esa señal en particular. (Las funciones de Shell son su amigo.)

+0

En realidad envío 'kill -s pid' a los niños pero pueden no atraparlo (incluso si se define 'trap 'Cleanup' 2'). entonces los niños son asesinados sin limpieza. La secuencia de comandos principal no sabe mucho sobre lo que están haciendo los niños, por lo que no puede manejar la limpieza por sí mismo. – Debugger

+0

@debugger: ¿Qué quiere decir con que los niños no pueden captar la señal? ¿Esa trampa está en el guión principal? Necesita estar en los niños. – Cascabel

+0

Jefromi: las trampas se especifican en los scripts principales y secundarios, aunque invocan funciones diferentes. Entonces, el guión principal captura la señal 'ctrl-c' y envía señales a los diferentes niños. Luego hay trampas definidas en los niños que "deberían" captar la señal del script principal y llamar a una función específica – Debugger

18

El siguiente ejemplo muestra un script primario que hace algo (sleep 5) después de que inicia dos hijos que hacen lo suyo (también sleep 5). Cuando el padre sale (por la razón que sea) le indica a los niños que terminen (no SIGINT, la terminación se señala con SIGTERM, también la señal predeterminada kill). Los niños luego hacen lo suyo en la recepción de SIGTERM. Si los niños son scripts propios, le recomiendo que cambie la trampa en TERM en una trampa en EXIT para que los niños limpien sin importar la causa de su terminación (siempre que sea interceptable).

Observe mi uso de wait. Bash no interrumpe el funcionamiento de comandos no integrados cuando recibe una señal. En cambio, espera a que se completen y maneja la señal una vez que se realiza el comando. Si usa wait, bash deja de esperar inmediatamente y maneja la señal de inmediato.

#!/usr/bin/env bash 

trap 'echo parent shutting down; kill $(jobs -p)' EXIT 

{ trap 'echo child 1 signaled' TERM; sleep 5 & wait; } & 
{ trap 'echo child 2 signaled' TERM; sleep 5 & wait; } & 

sleep 5 
+0

¿cómo se mata el sueño 5 en los niños cuando se envía una señal TERM a este script? – Gabriel

+0

¿No debería el tiempo de sueño de los niños ser más de 5 para el ejemplo? De esta manera, terminan antes de que el sueño en el padre haya terminado y 'kill' ya no puede encontrar los trabajos. –

0

encabezado principal PADRES ANTES DE LA ESCRITURA bucle principal :::

#Catch control-c and clean up testd instances if necessary 
cleanup() { 
    clear 
    echo "Caught Signal. Shutting Down MAIN." 
    if [ "$MAIN_on" -eq 1 ] 
    then 
    M_shutdown 
    fi 
    exit 1 
    } 

En el cuerpo principal de la secuencia de comandos, como desovar subprocesos que mantener una matriz con los identificadores de cada proc. Para cargar el PID en la matriz, establezca el valor en el último proceso generado, p. pon lo siguiente después de cada spawn sub-shell.

proc_id_array[1]=$! 

Contenido del M_shutdow serían algo así como ...

M_shutdown() { 

    if [ "$MAIN_on" -eq 1 ] 
    then 
    echo "Stopping Main" 
    echo "shutting down active subscripts" 
    count_proc_id=1 


while [ "$count_proc_id" -lt "$max_proc_id" ] 
     do 

      kill ${proc_id_array[$count_proc_id]} > /dev/null 2>&1 
      DATE=$(date +%m%d%y-%k:%M) 
      echo "$DATE: ${proc_name_array[$count_proc_id]} \(PID: ${proc_id_array[$count_proc_id]}\) stopped." >> $logfile    
      proc_id_array[$count_proc_id]="A" 
      count_proc_id=`expr $count_proc_id + 1` 
     done 


     echo "MAIN stopped" 
     MAIN_on=0 

     sleep 5 
     else 
     echo "MAIN already stopped." 
     sleep 1 
     fi 
    } 
4

¿Ha intentado: 1) Configure sus trampas en cada guión (maestro/niños) donde se los necesita 2) Enviar al maestro una matanza con él ha negado PID, para matar a todo el grupo de procesos , Quiero decir:

kill -15 -$PID 

hombre matar | grep -C1 Negativo

Cuestiones relacionadas