如何在停止时杀死 ruby​​ Thor 中的所有进程?

Posted

技术标签:

【中文标题】如何在停止时杀死 ruby​​ Thor 中的所有进程?【英文标题】:How to kill all processes inside ruby Thor on stop? 【发布时间】:2013-02-23 02:30:04 【问题描述】:

我在下面有一个脚本,它使用Thor 像管理ARGV 的rake 任务一样运行。

#!/usr/bin/env ruby
require "thor"

class Run < Thor

  desc "start", "start script"
  def start
      p1 = fork loop... 
      p2 = fork loop... 

      # 3 processes running

      Process.detach(p1)
      Process.waitpid(p1)

  end

  desc "stop", "stop script"      
  def stop
    # kill all 3 pids
  end

end

Run.start

启动ruby script.rb start时,会生成两个子进程(共三个)。我的问题是当我执行ruby script.rb stop 时如何杀死所有进程。我在网上看到,在启动时,我应该将 pid 父进程存储到一个文件中,当停止时,我读取它并杀死它。问题是杀死父母不会杀死孩子。所以我可以把这三个pid都保存在文件里,以后一一杀掉。

我在问自己什么是正确的方法,以及我在start 中处理进程的方式是否正确。

【问题讨论】:

在文件系统上存储 PID 似乎是守护程序服务的一种相当普遍的做法,在您的情况下,听起来确实将所有 PID 存储在文件系统上是有道理的,这是最可靠的杀死方式正确的流程。 感谢您的回答! 一种可能的替代方法是在对象获得 GC 时附加一个终结器,该终结器会在其自身之后正确清理。 ***.com/questions/5956067/ruby-destructors 你也可以使用 Daemons gem 来管理进程。 daemons.rubyforge.org 【参考方案1】:

如果你知道你的父 pid,你可以像这样找到并杀死所有的孩子:

# Find child pids, works on Linux / OSX
def child_pids(pid)
  pipe = IO.popen("ps -ef | grep #pid")
  pipe.readlines.map do |line|
    parts = line.strip.split(/\s+/)
    parts[1].to_i if parts[2] == pid.to_s and parts[1] != pipe.pid.to_s
  end.compact
end

# kill -9 every child
child_pids(parent_pid).each  |pid| Process.kill('TERM', pid) 

【讨论】:

以上是关于如何在停止时杀死 ruby​​ Thor 中的所有进程?的主要内容,如果未能解决你的问题,请参考以下文章

一个jvm中的java进程是不是有可能杀死/停止另一个jvm中的另一个java进程?

从 Eclipse 运行时如何杀死 Tomcat?

ForkManager SIGINT 只杀死 fork 中的当前进程

如何杀死并重新运行qt中的主进程?

如何使 systemd 杀死或停止重生 rsyslog 守护进程

错误:Thor:Class 的未定义方法“deprecation_warning”