2

サブプロセスを開始するRubyスクリプトがあります。プロセス全体が殺されたときに彼らを殺してほしい。

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

スクリプトを実行します。

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

精巣からの出力:

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)

Control-Cを押して、プロセスを強制終了します。実行中のプロセスを確認します。

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

testacularプロセスがまだ実行中であることがわかります。

それを手動で殺して、典型的なtestacularシャットダウン出力を見てください:

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] $ 

後でIO.popen手動で強制終了する必要がないように電話をかける方法はありますか?testacular

4

2 に答える 2

5

はい、メインプロセスにシグナルハンドラーをインストールしてCtrl-C(SIGINT)をトラップし、そのシグナルを子プロセスに送信する必要があります。

この例では、次のことを説明する必要があります。

# 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

出力:

> 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
于 2013-01-31T22:10:24.593 に答える
2

上記のアプローチは、シグナルが SIGKILL の場合は機能しないことに注意してください。これを修正するには、https ://github.com/vaneyckt/Adeona/blob/master/lib/adeona.rb に示すように、パイプベースのアプローチを実装できます。

于 2013-02-02T21:27:44.503 に答える