【问题标题】:Having a IO.popen command be killed when the caller process is killed当调用者进程被杀死时,有一个 IO.popen 命令被杀死
【发布时间】:2013-01-16 02:48:50
【问题描述】:

我有一个启动子进程的 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

我们可以看到睾丸进程仍在运行。

手动杀死它,看看典型的睾丸关闭输出:

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

【问题讨论】:

    标签: ruby process io popen kill


    【解决方案1】:

    是的,您只需在主进程中安装signal handler 以捕获 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
    

    【讨论】:

      【解决方案2】:

      请注意,当信号是 SIGKILL 时,上述方法不起作用。为了解决这个问题,您可以实现基于管道的方法,如下所示:https://github.com/vaneyckt/Adeona/blob/master/lib/adeona.rb

      【讨论】:

        猜你喜欢
        • 2013-08-19
        • 1970-01-01
        • 2010-12-08
        • 2017-01-23
        • 2010-12-02
        • 2013-09-19
        • 1970-01-01
        • 2011-09-09
        • 1970-01-01
        相关资源
        最近更新 更多