2013-01-31 1 views
2

J'ai un script Ruby qui démarre un sous-processus. Je veux qu'ils soient tués quand le processus global est tué.Avoir une commande IO.popen être tué lorsque le processus appelant est tué

IO.popen('testacular start unit.conf.js', 'w') 

Exécuter mon script:

user.name:/my/repo [git: my-branch] $ ruby my-script.rb 

Sortie de testacular:

user.name:/my/repo [git: my-branch] $ info: Testacular server started at http://localhost:8000/ 
info (launcher): Starting browser PhantomJS 
info (PhantomJS 1.7): Connected on socket id uVAO41Q2niyLA8AqbZ8w 
PhantomJS 1.7: Executed 44 of 44 SUCCESS (0.213 secs/0.115 secs) 

Hit Control-C pour tuer le processus. Vérifiez les processus en cours:

user.name:/my/repo [git: my-branch] $ ps 
    PID TTY   TIME CMD 
# ... 
39639 ttys019 0:01.28 node /usr/local/bin/testacular start unit.conf.js 
39649 ttys019 0:00.09 node /usr/local/bin/phantomjs /var/folders/2p/dklw3xys2n3f4hqmx73zvz6w0000gp/T/testacular-61981618/capture.js 
39650 ttys019 0:00.82 /usr/local/lib/node_modules/phantomjs/lib/phantom/bin/phantomjs /var/folders/2p/dklw3xys2n3f4hqmx73zvz6w0000gp/T/testacular-61981618/capture.js 

Nous pouvons voir que le processus testacular est toujours en cours d'exécution.

Tuez-le manuellement et voir la sortie d'arrêt testacular typique:

user.name:/my/repo [git: my-branch] $ kill 39639 
info: Disconnecting all browsers 
error (launcher): Cannot start PhantomJS 

user.name:/my/repo [git: my-branch] $ 

Y at-il un moyen de faire l'appel IO.popen tel que je ne dois pas tuer manuellement testacular plus tard?

Répondre

5

Oui, il vous suffit d'installer un signal handler dans votre processus principal pour intercepter Ctrl-C (SIGINT), puis envoyer ce signal au processus fils.

Cet exemple doit expliquer les choses:

# Start child and save its pid 
io = IO.popen("sleep 600") 
pid = io.pid 

# Print the output of the ps command (just for demonstration) 
puts "Checking #{pid} ..." 
system("ps #{pid}") 

puts "Installing signal handler..." 

Signal.trap("INT") { 
    # Ctrl-C was pressed... 
    puts "Caught interrupt - killing child..." 

    # Kill child process... 
    Process.kill("INT", pid) 

  # This prevents the process from becoming defunct 
    io.close 

    # Just for demonstration purposes - check that it died 
    puts "Checking #{pid} ..." 
    system("ps #{pid}") 

    # Forward the INT signal back to the parent 
    # ...or you could just call "exit" here too. 
    puts "Forwarding signal to myself..." 
    Signal.trap("INT", "DEFAULT") 
    Process.kill("INT", 0) 
} 

# Make the parent "do some stuff"... 
puts "Sleeping parent..." 
sleep 600 

Sortie:

> ruby popen_test.rb 
Checking 2474 ... 
    PID TTY  STAT TIME COMMAND 
2474 pts/0 S+  0:00 sleep 600 
Installing signal handler... 
Sleeping parent... 

# Press Ctrl-C ... 

Caught interrupt - killing child... 
Checking 2474 ... 
    PID TTY  STAT TIME COMMAND 
Forwarding signal to myself... 
kill.rb:20: Interrupt 
     from kill.rb:24:in `call' 
     from kill.rb:24:in `sleep' 
     from kill.rb:24 
+0

Génial, merci! –

Questions connexes