【发布时间】:2010-09-24 09:58:46
【问题描述】:
如果有不止一种方法,请列出它们。我只知道一个,但我想知道是否有一种更干净的 Ruby 方式。
【问题讨论】:
如果有不止一种方法,请列出它们。我只知道一个,但我想知道是否有一种更干净的 Ruby 方式。
【问题讨论】:
这就是我一直在做的:
def alive?(pid)
!!Process.kill(0, pid) rescue false
end
【讨论】:
rescue,但这似乎是合理的。
对于子进程,其他解决方案(如发送信号)不会按预期运行:它们将表明进程在实际退出时仍在运行。
如果您想检查您自己创建的进程,可以使用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。
【讨论】:
我之前已经处理过这个问题,昨天我将它编译到“process_exists”gem 中。
它向具有给定 pid 的进程发送空信号 (0) 以检查它是否存在。即使当前用户没有向接收进程发送信号的权限,它也可以工作。
用法:
require 'process_exists'
pid = 12
pid_exists = Process.exists?(pid)
【讨论】:
Linux下使用proc文件系统可以获得很多运行程序的属性:
File.read("/proc/#{pid}/cmdline")
File.read("/proc/#{pid}/comm")
【讨论】:
Process.getpgid 和Process::kill 方法之间的区别似乎在于 pid 存在但由另一个用户拥有时会发生什么。 Process.getpgid 将返回答案,Process::kill 将抛出异常 (Errno::EPERM)。
基于此,我推荐Process.getpgid,只是因为它可以让您不必捕获两个不同的异常。
这是我使用的代码:
begin
Process.getpgid( pid )
true
rescue Errno::ESRCH
false
end
【讨论】:
(Process.getpgid(pid) rescue nil).present?
仅*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
【讨论】:
@John T、@Dustin:实际上,伙计们,我仔细阅读了 Process rdocs,它看起来像
Process.getpgid( pid )
是应用相同技术的一种不那么暴力的方式。
【讨论】:
kill 0 是“暴力的”——这是一个错误。文档说:“如果 sig 为 0,则不发送任何信号,但仍会执行错误检查;这可用于检查进程 ID 或进程组 ID 是否存在。”
NotImplementedError (getpgid() function is unimplemented on this machine)。有什么帮助吗?
你可以试试
Process::kill 0, pid
其中 pid 是 pid 号,如果 pid 正在运行,它应该返回 1。
【讨论】:
如果它是您希望“拥有”的进程(例如,您正在使用它来验证您控制的进程的 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
>>
【讨论】: