2010-03-26 14 views
20

Ich habe eine Sammlung von Skripten, die von einem Haupt gesteuert werden. Ich möchte das Signal ctrl + c im Hauptskript abfangen und es zu den anderen propagieren. Die anderen Skripte sollten dieses Signal ebenfalls abfangen (aus dem Hauptskript) und etwas sauber machen ...Wie propagiert man ein Signal durch eine Sammlung von Skripten?

Ich habe versucht, die Kinder an die kill -s SIGINT zu senden, aber sie scheinen, dass sie das Signal nicht abfangen können (sogar Wenn trap 'Cleanup' SIGINT in den untergeordneten Skripten definiert ist)

Irgendwelche Hinweise, wie dies zu realisieren ist?

+1

Es wäre hilfreich, wenn Sie bestimmte Beispiele für ein verkürztes Elternteil und Kind zeigen. –

+0

Siehe meine Antwort auf Ihre andere Frage für eine mögliche Lösung. http://stackoverflow.com/questions/2524937/how-to-send-a-signal-sigint-from-script-to-script-bash –

Antwort

-1

Ich bin nicht sicher, was meinst du mit "andere Skripte sollten dieses Signal vom Hauptskript abfangen"? Wie kann ein Subprozessskript Code im Hauptskript verwenden, um ein Signal zu fangen?

Ich möchte nicht versuchen, viel Code für Sie zu schreiben, weil ich nicht genau weiß, was Sie mit "Skripts von einem Haupt" entweder bedeuten, aber vermutlich starten Sie einige Teilprozesse und dann eine Regelschleife, die prüft, ob die anderen Skripte beendet wurden, und können ihren Exit-Status abrufen? Wenn das der Fall ist, ist es für mich am sinnvollsten, wenn jedes Skript seine eigenen Überfüllungen und Bereinigungen durchführt. Wenn das Hauptskript ein Signal abfängt, kann es gegebenenfalls das Signal an alle Kinder weitergeben (über kill -s <signal> pid). Wenn ein untergeordneter Prozess ein Signal abfängt, kann er einen Beendigungsstatus zurückgeben, der angibt, dass er durch dieses Signal beendet wurde. Der main kann dann diesen Exit-Status entsprechend behandeln - vielleicht auf die gleiche Weise, als hätte er dieses bestimmte Signal selbst erhalten. (Shell-Funktionen sind Ihr Freund.)

+0

Eigentlich sende ich 'kill -s pid' an die Kinder, aber sie können fange es nicht (auch wenn 'falle '' 2 'definiert ist). So werden die Kinder ohne Aufräumarbeiten getötet. Das Hauptskript weiß nicht viel darüber, was die Kinder machen, deshalb kann er die Säuberung nicht alleine durchführen. – Debugger

+0

@debugger: Was meinst du damit, dass die Kinder das Signal nicht verstehen können? Ist diese Falle im Hauptskript? Es muss in den Kindern sein. – Cascabel

+0

Jefromi: Traps werden sowohl für Haupt- als auch für Kinderskripts angegeben, obwohl sie unterschiedliche Funktionen aufrufen. So fängt das Hauptskript das 'ctrl-c'-Signal ein und sendet Signale an die verschiedenen Kinder. Dann gibt es auf Kindern definierte Traps, die das Signal vom Hauptskript "fangen" sollten und eine bestimmte Funktion aufrufen. – Debugger

18

Das folgende Beispiel veranschaulicht ein übergeordnetes Skript, das etwas (sleep 5) ausführt, nachdem es zwei untergeordnete Objekte startet, die ihr eigenes Ding (auch sleep 5) ausführen. Wenn das Elternteil (aus welchen Gründen auch immer) endet, signalisiert es den Kindern, zu beenden (do not SIGINT, Beendigung wird durch SIGTERM, auch das Standardsignal kill signalisiert). Die Kinder machen dann ihr Ding an der Rezeption von SIGTERM. Wenn die Kinder selbst Skripte sind, empfehle ich Ihnen, die Falle auf in eine Falle auf EXIT zu ändern, damit die Kinder aufräumen, egal was die Ursache ihrer Beendigung sein sollte (solange sie feststellbar ist).

Beachten Sie meine Verwendung von wait. Bash unterbricht nicht das Ausführen nicht eingebauter Befehle, wenn es ein Signal empfängt. Stattdessen wartet es auf ihre Fertigstellung und behandelt das Signal, nachdem der Befehl ausgeführt wurde. Wenn Sie wait verwenden, stoppt Bash sofort und behandelt das Signal sofort.

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

Wie wird der Schlaf 5 in den Childs getötet, wenn ein TERM-Signal an dieses Skript gesendet wird? – Gabriel

+0

Sollte der Schlaf bei den Kindern nicht länger als 5 sein? So enden sie, bevor der Schlaf im Elternteil beendet ist und 'kill' die Jobs nicht mehr finden kann. –

0

MAIN ELTERN SCRIPT Header vor der Hauptschleife :::

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

Im Hauptteil des Skripts, wie Sie Subprozesse laichen halten Sie ein Array mit dem proc-IDs von jedem. Um die PID in das Array zu laden, setzen Sie den Wert auf den zuletzt erzeugten Prozess, z. setze nach jedem Subshell-Spawn folgendes ein:

proc_id_array[1]=$! 

Inhalt des M_shutdow wäre etwas wie ...

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

Haben Sie versucht zu: 1) Richten Sie Ihre Fallen in jedem Skript (Master/Kinder), wo man sie 2) Senden an den Master benötigen eine Abtötung mit ihm ist PID negiert, die gesamte Prozessgruppe zu töten , Ich meine:

kill -15 -$PID 

man töten | grep -C1 Negativ