How can I determine if a different process id is r

2019-04-02 05:57发布

问题:

I need to see if a given process id is running, and it must work in either Java or JRuby (preferably a Ruby solution). It can be system dependent for Linux (specifically Debian and/or Ubuntu).

I already have the PID I am looking for, just need to see if it is currently running.


UPDATE:

Thanks for all the responses everyone! I appreciate it, however it's not QUITE what I'm looking for... I am hoping for something in a standard Ruby library (or Java, but preferably Ruby)... if no such library call exists, I will probably stick with the procfs solution I already have.

回答1:

Darron's comment was spot on, but rather than calling the "kill" binary, you can just use Ruby's Process.kill method with the 0 signal:

#!/usr/bin/ruby 

pid = ARGV[0].to_i

begin
    Process.kill(0, pid)
    puts "#{pid} is running"
rescue Errno::EPERM                     # changed uid
    puts "No permission to query #{pid}!";
rescue Errno::ESRCH
    puts "#{pid} is NOT running.";      # or zombied
rescue
    puts "Unable to determine status for #{pid} : #{$!}"
end

[user@host user]$ ./is_running.rb 14302
14302 is running

[user@host user]$ ./is_running.rb 99999
99999 is NOT running.

[user@host user]$ ./is_running.rb 37
No permission to query 37!

[user@host user]$ sudo ./is_running.rb 37
37 is running

Reference: http://pleac.sourceforge.net/pleac_ruby/processmanagementetc.html



回答2:

Unix has a special feature of the kill system call around signal zero. Error checking is performed, but no signal is sent.

def pid_exists? (pid)
    system "kill -0 #{pid}"
    return $? == 0
end

One caveat: this won't detect processes with that pid that you don't have permission to signal.



回答3:

From my answer to this question, I was thinking of just using procfs again, by checking if the given directory exists via File.exist? "/proc/#{pid}". This worked in jirb:

irb(main):001:0> File.exist? "/proc/5555"
=> false
irb(main):002:0> File.exist? "/proc/7677"
=> true

However, I would still prefer to use a method that specifically exists to detect if a process is running... like Process.exist?(pid)... which unfortunately doesn't exist that I've seen.



回答4:

I can't speak for JRuby, but in Java, the only way to check is if you launched the process from Java (in which case you would have an instance of Process that you could do things with).



回答5:

You'll probably want to double check for the JVM that you're using. But if you send a SIGQUIT signal kill -3 I believe, (I don't have a terminal handy). That should generate a Javacore file which will have stack traces of the in use thread, check for JRuby packages in that file.

It shouldn't terminate or anything but as always be careful sending signals.



回答6:

If you don't mind creating a whole new process then this lazy way should work:

def pid_exists? (pid)
    system "ps -p #{pid} > /dev/null"
    return $? == 0
end

For most variations of ps, it should return 0 on success and non-zero on error. The usual error with the usage above will be not finding the process with the given PID. The version of ps I have under Ubuntu returns 256 in this case.

You could also use Process.kill to send a signal of 0 to the process (signal 0 indicates if a signal may be sent), but that seems to only work if you own the process you're sending the signal to (or otherwise have permissions to send it signals).



回答7:

You could use the command line tool jps which comes with your java installation. jps lists all java Processes of a user.

E.g.

>jps -l
5960 org.jruby.Main
2124 org.jruby.Main
5376 org.jruby.Main
4428 sun.tools.jps.Jps

Or if you need to get the results into your script you could use %x[..]:

>> result = %x[jps -l]
=> "5960 org.jruby.Main\n2264 sun.tools.jps.Jps\n2124 org.jruby.Main\n5376 org.jruby.Main\n"
>> p result
"5960 org.jruby.Main\n2264 sun.tools.jps.Jps\n2124 org.jruby.Main\n5376 org.jruby.Main\n"
=> nil