2010-03-26 12 views
20

Ho una collezione di script che sono controllati da uno principale. Voglio intercettare il segnale ctrl + c nello script principale e propagarlo agli altri. Gli altri script dovrebbe trappola questo segnale così (dallo script principale) e fare un po 'di pulizia ...Come propagare un segnale attraverso una raccolta di script?

ho cercato di inviare kill -s SIGINT ai bambini, ma sembrano non sono in grado di catturare il segnale (anche se trap 'Cleanup' SIGINT viene definito negli script figli)

Eventuali indizi su come realizzare questo?

+1

Sarebbe utile mostrare esempi specifici di genitore e bambino abbreviato. –

+0

Vedi la mia risposta alla tua altra domanda per una possibile soluzione. http://stackoverflow.com/questions/2524937/how-to-send-a-signal-sigint-from-script-to-script-bash –

risposta

-1

Non sono sicuro di cosa intendi per "altri script dovrebbero intercettare questo segnale dallo script principale"? Come può uno script di sottoprocesso utilizzare il codice nello script principale per intercettare un segnale?

Non voglio provare a scrivere molto codice per te perché non so esattamente cosa intendi per "script controllati da uno principale", ma presumibilmente tu lanci alcuni sottoprocessi quindi hai un ciclo di controllo che controlla se gli altri script sono usciti e può accedere al loro stato di uscita? Se è così, la cosa che ha più senso per me è che ogni script faccia il suo trapping e cleanup. Quando lo script principale intercetta un segnale, può, se lo si desidera, trasmettere il segnale a tutti i bambini (tramite kill -s <signal> pid). Quando un processo figlio intercetta un segnale, può restituire uno stato di uscita che indica che è stato terminato da quel segnale. Il principale può quindi gestire lo stato di uscita in modo appropriato, forse nello stesso modo in cui avrebbe ricevuto quel particolare segnale stesso. (Funzioni di shell sono tuo amico.)

+0

In realtà mando 'kill -s pid' ai bambini ma possono non prenderlo (anche con 'trap 'Cleanup' 2 'in corso di definizione). così i bambini vengono uccisi senza ripulire. La sceneggiatura principale non sa molto su cosa stanno facendo i bambini, quindi non può gestire da solo la pulizia – Debugger

+0

@debugger: cosa vuoi dire che i bambini non riescono a prendere il segnale? Quella trappola è nella sceneggiatura principale? Deve essere nei bambini. – Cascabel

+0

Jefromi: i trap sono specificati su entrambi gli script principale e secondario, sebbene chiamino funzioni diverse. Quindi lo script principale cattura il simbolo 'ctrl-c' e invia segnali ai diversi bambini. Poi ci sono trappole definite sui bambini che "dovrebbero" intercettare il segnale dallo script principale e chiamare una funzione specifica – Debugger

18

L'esempio seguente mostra uno script genitore che fa qualcosa (sleep 5) dopo l'avvio di due figli che fanno le loro cose (anche sleep 5). Quando il genitore esce (per qualsiasi motivo) segnala ai bambini di terminare (non SIGINT, la terminazione è segnalata da SIGTERM, anche il segnale di default kill). I bambini poi fanno le loro cose alla reception di SIGTERM. Se i bambini sono script propri, ti consiglio di cambiare la trappola su TERM in una trappola su EXIT in modo che i bambini si puliscano indipendentemente dalla causa della loro terminazione (a condizione che siano intercettabili).

Avviso il mio utilizzo di wait. Bash non interrompe l'esecuzione di comandi non incorporati quando riceve un segnale. Invece, attende che si completino e gestiscano il segnale dopo che il comando è stato eseguito. Se si utilizza wait, bash interrompe l'attesa immediatamente e gestisce il segnale immediatamente.

#!/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

come viene ucciso il sonno 5 nei childs quando viene inviato un segnale TERM a questo script? – Gabriel

+0

Non dovrebbe il sonno nei bambini essere più lungo di 5 per l'esempio? In questo modo, finiscono prima che il sonno nel genitore sia terminato e 'kill' non riesca più a trovare i lavori. –

0

PRINCIPALE GENITORE SCRIPT HEADER prima del Main LOOP :::

#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 
    } 

Nel corpo principale dello script, come si spawn sottoprocessi si mantiene un array con gli ID di ogni proc. Per caricare il PID nell'array, impostare il valore dell'ultimo processo generato, ad es. metti quanto segue dopo ogni spawn sub-shell.

proc_id_array[1]=$! 

Il contenuto di M_shutdow sarebbe qualcosa come ...

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

Hai provato a: 1) Setup vostre trappole in tutti gli script (master/bambini) in cui è necessario li 2) Inviare al master un uccidere con il suo PID negata, per uccidere l'intero gruppo di processi , voglio dire:

kill -15 -$PID 

uomo uccide | grep -C1 Negativo

Problemi correlati