我有一些奇怪的问题。
我们正在使用Xvfb虚拟桌面管理器,并希望在继续之前确保它正在运行。使用纯shell,我可以很容易地做到这一点:
ps -ef | grep Xvfb | grep -v grep
这正是我所需要的,一行包含了关于Xvfb进程的信息。接下来,我想把它合并到我的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()每次都得到null。
我也试过:
ps -ef | grep Xvfb | grep -v grep | awk {'print $2'}
只是为了获取进程ID。还有,运气不好。
有没有其他人经历过或者知道我做错了什么?
5条答案
按热度按时间hs1rzwqc1#
你在尝试使用“|“,这是shell特有的管道函数,因此不能在java进程中执行此操作。您可以尝试使用
pidof Xvfb
获取进程ID。ztyzrc3y2#
也许
Runtime.getRuntime().exec()
试图执行程序,因为它是在参数中。也就是说,它运行程序ps
与参数-ef
,|
,grep
等。所以,程序失败,因为它不知道发生了什么。如果需要运行管道命令,则应显式调用shell:
deyfvvtc3#
当你直接执行你的命令字符串时,你不会得到一个shell,它是处理管道的shell。|grep Xvfb| grep -v grep"”
dsekswqp4#
有很多方法可以实现这一点。你可以使用
java.lang.ProcessBuilder
和“pgrep”来获取进程ID(PID),如下所示:pgrep -fl java | awk {'print $1'}
。或者,如果您是在Linux下执行,则可以查询/proc
目录。我知道,这看起来很可怕,不可移植,甚至实现得很差,我同意。但是因为Java实际上是在VM中运行的,出于一些荒谬的原因,我在JDK工作了15年之后,真的搞不懂,这就是为什么不可能看到JVM空间之外的东西,如果你仔细想想,这真的很荒谬。你可以做其他任何事情,甚至是fork和join子进程(* 当世界不知道threads或pthreads时,这是一种可怕的多任务处理方式,真是见鬼!Java到底怎么了?!*:)。
我知道这会给予很大的讨论,但无论如何,有一个非常好的API,我已经在我的项目中使用过了,它足够稳定(它是OSS,所以在真正信任该API之前,您仍然需要对您使用的每个版本进行压力测试):https://github.com/jezhumble/javasysmon
JavaDoc:http://jezhumble.github.io/javasysmon/,搜索类
com.jezhumble.javasysmon.OsProcess
,她会做到这一点。希望它能帮上忙,祝你好运。xvw2m8pv5#
不确定这是否有帮助,但我只是必须检查我的应用程序的另一个示例是否在Linux中运行,所以我实现了这一点,它可以返回另一个示例的计数或PID(这样我就可以放在前面并停止加载新示例)。