【问题标题】:How can I check from Ruby whether a process with a certain pid is running?如何从 Ruby 检查具有特定 pid 的进程是否正在运行?
【发布时间】:2010-09-24 09:58:46
【问题描述】:

如果有不止一种方法,请列出它们。我只知道一个,但我想知道是否有一种更干净的 Ruby 方式。

【问题讨论】:

    标签: ruby process pid


    【解决方案1】:

    这就是我一直在做的:

    def alive?(pid)
      !!Process.kill(0, pid) rescue false
    end
    

    【讨论】:

    • 你通常不想像那样使用rescue,但这似乎是合理的。
    【解决方案2】:

    对于子进程,其他解决方案(如发送信号)不会按预期运行:它们将表明进程在实际退出时仍在运行。

    如果您想检查您自己创建的进程,可以使用Process.waitpid。如果您使用 Process::WNOHANG 标志,则调用不会阻塞,只要子进程没有退出,就会返回 nil

    例子:

    pid = Process.spawn('sleep 5')
    Process.waitpid(pid, Process::WNOHANG) # => nil
    sleep 5
    Process.waitpid(pid, Process::WNOHANG) # => pid
    

    如果 pid 不属于子进程,则会抛出异常 (Errno::ECHILD: No child processes)。

    这同样适用于Process.waitpid2

    【讨论】:

    • 我发现这比上述解决方案更可靠。谢谢!
    • 谢谢,这是衍生进程最可靠的答案。对于非我们的进程,其他解决方案都可以。
    • 这似乎是唯一适用于 Windows 的答案,至少对我而言:D
    【解决方案3】:

    我之前已经处理过这个问题,昨天我将它编译到“process_exists”gem 中。

    它向具有给定 pid 的进程发送空信号 (0) 以检查它是否存在。即使当前用户没有向接收进程发送信号的权限,它也可以工作。

    用法:

    require 'process_exists'
    
    pid = 12
    pid_exists = Process.exists?(pid)
    

    【讨论】:

      【解决方案4】:

      Linux下使用proc文件系统可以获得很多运行程序的属性:

      File.read("/proc/#{pid}/cmdline")
      File.read("/proc/#{pid}/comm")
      

      【讨论】:

        【解决方案5】:

        Process.getpgidProcess::kill 方法之间的区别似乎在于 pid 存在但由另一个用户拥有时会发生什么。 Process.getpgid 将返回答案,Process::kill 将抛出异常 (Errno::EPERM)

        基于此,我推荐Process.getpgid,只是因为它可以让您不必捕获两个不同的异常。

        这是我使用的代码:

        begin
          Process.getpgid( pid )
          true
        rescue Errno::ESRCH
          false
        end
        

        【讨论】:

        • 我如何杀死另一个用户拥有的进程?
        • oneliner:(Process.getpgid(pid) rescue nil).present?
        【解决方案6】:

        *nix 的方法是转至ps 并检查返回的字符串中是否存在\n(新行)分隔符。

        IRB 输出示例

        1.9.3p448 :067 > `ps -p 56718`                                                          
        "  PID TTY           TIME CMD\n56718 ttys007    0:03.38 zeus slave: default_bundle   \n"
        

        打包为方法

        def process?(pid)  
          !!`ps -p #{pid.to_i}`["\n"]
        end
        

        【讨论】:

          【解决方案7】:

          @John T、@Dustin:实际上,伙计们,我仔细阅读了 Process rdocs,它看起来像

          Process.getpgid( pid )
          

          是应用相同技术的一种不那么暴力的方式。

          【讨论】:

          • 我发现这可能会在最新的 Ubuntu 上返回误报(它报告正在运行,但实际上它没有运行)。我不知道为什么,但我在这个线程中只有@balu 的解决方案似乎对我有用。
          • 我猜这不是一个跨平台的解决方案。 (它不能在 Windows 上运行,对吧?)
          • 我认为这里的含义是kill 0 是“暴力的”——这是一个错误。文档说:“如果 sig 为 0,则不发送任何信号,但仍会执行错误检查;这可用于检查进程 ID 或进程组 ID 是否存在。”
          • 在 Windows 机器中获取 NotImplementedError (getpgid() function is unimplemented on this machine)。有什么帮助吗?
          • @ManivannanJeganathan 这在 Windows 上不起作用。请改用其他解决方案。 (也许this one)。
          【解决方案8】:

          你可以试试

          Process::kill 0, pid
          

          其中 pid 是 pid 号,如果 pid 正在运行,它应该返回 1。

          【讨论】:

            【解决方案9】:

            如果它是您希望“拥有”的进程(例如,您正在使用它来验证您控制的进程的 pid),您可以发送 sig 0 给它。

            >> Process.kill 0, 370
            => 1
            >> Process.kill 0, 2
            Errno::ESRCH: No such process
                from (irb):5:in `kill'
                from (irb):5
            >> 
            

            【讨论】:

            • 有趣的方法!我会调查此事。
            • 该死,打败我。我看到“已发布新答案”的事情,我的心沉了下去:(
            • 但是信号 0 是什么?小便?
            • 来自我的手册页:然而,值为 0 将导致执行错误检查(不发送信号)。这可以用来检查pid的有效性。
            • 不幸的是,如果进程处于“僵尸”状态,这也会返回 1,因此不会告诉您进程是否已死,只是系统某处是否存在具有该 PID 的进程(例如例如,如果您有一个进程的开放流,即使进程已终止,这也将返回 1)。另请注意,操作系统可以重复使用 PID...
            猜你喜欢
            • 2011-06-06
            • 2014-03-06
            • 2010-10-08
            • 2016-01-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多