我有一些奇怪的问题。
我们正在使用Xvfb虚拟桌面管理器,并希望在继续之前确保它正在运行。使用纯shell,我可以轻松地做到这一点:
ps -ef | grep Xvfb | grep -v grep
这正是我所需要的,一行包含有关Xvfb proc的信息。接下来,我想将它合并到我的Java程序中并解析结果并存储正在运行的Xvfb进程的PID。我正在尝试这个:
String line;
try {
Process p = Runtime.getRuntime().exec("ps -ef | grep Xvfb | grep -v grep");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()));
while ((line = input.readLine()) != null)
{
System.out.println(line);
}
} catch (Exception err) {
System.out.println(err);
}
奇怪的是,如果我使用“ps -ef”,当我运行我的应用程序时,我会收到一个大量的进程转储到我的控制台。但是,如果我使用| grep缩小返回的进程列表,我得到零结果。 input.readLine()每次都为空。
我也尝试过:
ps -ef | grep Xvfb | grep -v grep | awk {'print $2'}
要抓住进程ID。而且,没有运气。
有没有其他人经历过这个或知道我做错了什么?
答案 0 :(得分:5)
你正在尝试使用“|”这是一个特定于shell的管道函数,因此您无法在Java进程中执行此操作。您可以尝试使用pidof Xvfb
来获取进程ID。
答案 1 :(得分:3)
也许Runtime.getRuntime().exec()
尝试执行程序中的程序。也就是说,它使用参数ps
,-ef
,|
等运行程序grep
。因此,程序失败,因为它无法理解正在发生的事情。< / p>
如果你需要运行管道命令,你应该明确地调用shell:
Runtime.getRuntime().exec(new String[] {"sh", "-c", "ps -ef | grep Xvfb | grep -v grep"});
答案 2 :(得分:2)
当你直接执行你的命令字符串时,你没有得到一个shell,它是处理管道的shell。所以,你会执行像“/ bin / sh -e \”ps -ef |这样的东西grep Xvfb | grep -v grep \“”
答案 3 :(得分:1)
有很多方法可以做到这一点。您可以使用java.lang.ProcessBuilder
和“pgrep”来获取进程ID(PID),例如:pgrep -fl java | awk {'print $1'}
。或者,如果您在Linux下运行,则可以查询/proc
目录。
我知道,这似乎很糟糕,而且不便携,甚至执行不力,我同意。但是因为Java实际上是在VM中运行的,出于一些荒谬的原因,我在JDK工作超过15年之后无法弄清楚,这就是为什么不可能看到JVM空间以外的东西,如果你真的很荒谬想一想。你可以做其他所有事情,甚至分叉和加入子进程(当世界不知道线程或 pthreads 时,那些是多任务的可怕方式,什么地狱!Java正在发生什么?! :)。
这将给出我所知道的一个巨大的讨论,但无论如何,我已经在我的项目中使用了一个非常好的API并且它足够稳定(它是OSS所以你仍然需要在真正信任API之前对你使用的每个版本进行压力测试):https://github.com/jezhumble/javasysmon
JavaDoc:http://jezhumble.github.io/javasysmon/,搜索班级com.jezhumble.javasysmon.OsProcess
,她会做的伎俩。希望它有所帮助,祝你好运。