2010-03-26 3 views
20

J'ai une collection de scripts qui sont contrôlés par un principal. Je veux piéger le signal ctrl + c dans le script principal et le propager aux autres. Les autres scripts devraient aussi piéger ce signal (du script principal) et faire un peu de nettoyage ...Comment propager un signal à travers une collection de scripts?

J'ai essayé d'envoyer kill -s SIGINT aux enfants, mais ils semblent être incapables d'attraper le signal (même si trap 'Cleanup' SIGINT étant défini sur les scripts enfants)

Des indices pour réaliser ceci?

+1

Il serait utile que vous montriez des exemples spécifiques d'un parent abrégé et d'un enfant. –

+0

Voir ma réponse à votre autre question pour une solution possible. http://stackoverflow.com/questions/2524937/how-to-send-a-signal-sigint-from-script-to-script-bash –

Répondre

-1

Je ne suis pas sûr de savoir ce que vous entendez par "d'autres scripts devraient piéger ce signal du script principal"? Comment un script de sous-processus peut-il utiliser du code dans le script principal pour intercepter un signal? Je ne veux pas essayer d'écrire beaucoup de code pour vous parce que je ne sais pas exactement ce que vous voulez dire par "scripts contrôlés par un principal" non plus, mais vraisemblablement vous lancez des sous-processus alors que vous avez une boucle de contrôle vérifie si les autres scripts ont quitté, et peut récupérer leur statut de sortie? Si c'est le cas, la chose qui me semble la plus logique est que chaque script fasse son propre piégeage et nettoyage. Lorsque le script principal piège un signal, il peut si vous le souhaitez transmettre le signal à tous les enfants (via kill -s <signal> pid). Lorsqu'un processus enfant intercepte un signal, il peut renvoyer un état de sortie indiquant qu'il a été interrompu par ce signal. Le principal peut alors gérer ce statut de sortie de manière appropriée - peut-être de la même manière que s'il avait lui-même reçu ce signal particulier. (Les fonctions Shell sont votre ami.)

+0

En fait j'envoie 'kill -s pid' aux enfants mais ils peuvent ne l'attrape pas (même si 'trap 'Cleanup' 2' est défini). alors les enfants sont tués sans nettoyage. Le script principal ne sait pas grand-chose de ce que font les enfants, donc il ne peut pas gérer le nettoyage lui-même. – Debugger

+0

@debugger: Que voulez-vous dire par les enfants qui ne peuvent pas attraper le signal? Est-ce que c'est un piège dans le script principal? Il doit être dans les enfants. – Cascabel

+0

Jefromi: les traps sont spécifiés sur les scripts principaux et enfants, bien qu'ils appellent des fonctions différentes. Ainsi, le script principal attrape le signal 'ctrl-c' et envoie des signaux aux différents enfants. Ensuite, il y a des pièges définis sur les enfants qui "devraient" attraper le signal du script principal et appeler une fonction spécifique – Debugger

18

L'exemple suivant illustre un script parent qui fait quelque chose (sleep 5) après le démarrage de deux enfants qui font leur propre chose (également sleep 5). Lorsque le parent quitte (pour une raison quelconque), il signale aux enfants de se terminer (ne pas SIGINT, la terminaison est signalée par SIGTERM, également le signal par défaut kill). Les enfants font alors leur chose à la réception de SIGTERM. Si les enfants sont leurs propres scripts, je vous recommande de changer le piège sur TERM dans un piège sur EXIT afin que les enfants nettoient quelle que soit la cause de leur résiliation (tant qu'il est trappable).

Notez mon utilisation de wait. Bash n'interrompt pas les commandes non intégrées lors de la réception d'un signal. Au lieu de cela, il attend qu'ils complètent et manipule le signal une fois la commande terminée. Si vous utilisez wait, bash arrête d'attendre immédiatement et gère le signal immédiatement.

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

comment le sommeil 5 est-il tué dans les enfants lorsqu'un signal TERM est envoyé à ce script? – Gabriel

+0

Est-ce que le sommeil chez les enfants ne devrait pas être plus long que 5 pour l'exemple? Comme ça, ils finissent avant que le sommeil dans le parent ne soit terminé et que 'kill' ne trouve plus les emplois. –

0

MAIN PARENT HEADER SCRIPT AVANT LA 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 
    } 

Dans le corps principal du script, comme vous engendrez vous maintenir sous-processus un tableau avec les proc ids de chacun. Pour charger le PID dans le tableau, définissez la valeur du dernier processus engendré par exemple. mettre le suivant après chaque sous-shell spawn.

proc_id_array[1]=$! 

Contenu du M_shutdow serait quelque chose comme ...

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

Avez-vous essayé de: 1) Configurez vos pièges dans chaque script (maître/Childs) où vous en avez besoin 2) Envoyer au maître une mise à mort avec elle est PID niée, de tuer tout le groupe de processus , Je veux dire:

kill -15 -$PID 

homme tuer | grep -C1 Négatif

Questions connexes