【发布时间】:2010-09-13 09:05:03
【问题描述】:
我需要在 Linux 平台上找到当前正在运行的进程的 PID(它可以是系统相关的解决方案)。 Java 不支持获取进程 ID,并且 JRuby 目前存在 Ruby 方法 Process.pid 的错误。
还有其他方法可以获取 PID 吗?
【问题讨论】:
-
Process.pid 不再损坏,至少从 jruby 1.7.23 开始
我需要在 Linux 平台上找到当前正在运行的进程的 PID(它可以是系统相关的解决方案)。 Java 不支持获取进程 ID,并且 JRuby 目前存在 Ruby 方法 Process.pid 的错误。
还有其他方法可以获取 PID 吗?
【问题讨论】:
如果你安装了procfs,你可以通过/proc/self符号链接找到进程id,它指向一个名为pid的目录(这里还有其他相关信息的文件,包括PID,但在这种情况下,您只需要目录)。
因此,使用 Java,您可以:
String pid = new File("/proc/self").getCanonicalFile().getName();
在 JRuby 中,您可以使用相同的解决方案:
pid = java.io.File.new("/proc/self").canonical_file.name
特别感谢免费节点上的#stackoverflow 频道帮助我解决了这个问题! (具体来说,Jerub、gregh 和 Topdeck)
【讨论】:
仅在使用 Sun JVM 的 Linux 中测试。可能不适用于其他 JMX 实现。
String pid = ManagementFactory.getRuntimeMXBean().getName().split("@")[0];
【讨论】:
可以使用JNI接口调用POSIX函数getpid()。这很简单。您从所需的 POSIX 函数的类开始。我叫它POSIX.java:
import java.util.*;
class POSIX
{
static { System.loadLibrary ("POSIX"); }
native static int getpid ();
}
用
编译$ javac POSIX.java
之后你生成一个头文件POSIX.h
$ javah -jni POSIX
头文件包含函数的 C 原型,其中包含 getpid 函数。现在您必须实现该功能,这很容易。我在POSIX.c:
#include "POSIX.h"
#include <sys/types.h>
#include <unistd.h>
JNIEXPORT jint JNICALL Java_POSIX_getpid (JNIEnv *env, jclass cls)
{
return getpid ();
}
现在你可以使用 gcc 编译它了:
$ gcc -Wall -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include -I/usr/lib/jvm/java-1.6.0-sun-1.6.0.21/include/linux -o libPOSIX.so -shared -Wl,-soname,libPOSIX.so POSIX.c -static -lc
您必须指定 Java 的安装位置。就这样。现在你可以使用它了。创建一个简单的 getpid 程序:
public class getpid
{
public static void main (String argv[])
{
System.out.println (POSIX.getpid ());
}
}
用javac getpid.java 编译并运行它:
$ java getpid &
[1] 21983
$ 21983
第一个 pid 由 shell 编写,第二个由 Java 程序在 shell 提示符返回后编写。 ∎
【讨论】:
生成一个 shell 进程来读取其父进程的 pid。那一定是我们的pid。这是运行代码,没有异常和错误处理。
import java.io.*;
import java.util.Scanner;
public class Pid2
{
public static void main(String sArgs[])
throws java.io.IOException, InterruptedException
{
Process p = Runtime.getRuntime().exec(
new String[] { "sh", "-c", "ps h -o ppid $$" });
p.waitFor();
Scanner sc = new Scanner(p.getInputStream());
System.out.println("My pid: " + sc.nextInt());
Thread.sleep(5000);
}
}
如果要获取 PID 只是为了发出另一个 shell 命令,这个解决方案似乎是最好的。将命令包含在反引号中以将其作为参数传递给另一个命令就足够了,例如:
nice `ps h -o ppid $$`
这可能会替换给exec调用的数组中的最后一个字符串。
【讨论】:
你可以试试JNR-Posix中的getpid()。
它还有一个 Windows POSIX 包装器,它从 libc 中调用 getpid()。不需要 JNI。
【讨论】:
Java 9 终于提供了一个正式的方式来使用ProcessHandle:
ProcessHandle.current().pid();
这个:
首先获取当前进程的ProcessHandle 引用。
为了访问其pid。
无需导入,因为 ProcessHandle 是 java.lang 的一部分。
【讨论】: