5

我对此有一些奇怪的问题。

我们正在使用 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。此外,没有运气。

有没有其他人经历过这个或知道我做错了什么?

4

4 回答 4

5

您正在尝试使用“|” 这是一个特定于 shell 的管道函数,因此您不能在 java 进程中执行此操作。您可以尝试使用pidof Xvfb.

于 2011-12-07T21:15:11.380 回答
4

也许Runtime.getRuntime().exec()会尝试按照参数中的方式执行程序。也就是说,它ps使用参数-ef|grep等运行程序。因此,程序失败是因为它不了解正在发生的事情。

如果需要运行管道命令,则应显式调用 shell:

Runtime.getRuntime().exec(new String[] {"sh", "-c", "ps -ef | grep Xvfb | grep -v grep"});
于 2011-12-07T21:17:27.290 回答
2

当你直接执行你的命令字符串时,你不会得到一个 shell,它是处理管道的 shell。所以,你会执行类似 "/bin/sh -e \"ps -ef | grep Xvfb | grep -v grep\""

于 2011-12-07T21:16:59.737 回答
1

有很多方法可以做到这一点。您可以使用java.lang.ProcessBuilder和“pgrep”来获取进程ID(PID),例如:pgrep -fl java | awk {'print $1'}。或者,如果您在 Linux 下运行,您可以查询该/proc目录。

我知道,这看起来很可怕,而且不可移植,甚至实施得很差,我同意。但是因为 Java 实际上是在 VM 中运行的,出于某种荒谬的原因,我在 JDK 工作超过 15 年之后我无法真正弄清楚,这就是为什么无法看到 JVM 空间之外的东西,如果你真的很荒谬想想看。你可以做其他所有事情,甚至 fork 和 join 子进程(当世界不知道线程pthreads时,这些是一种可怕的多任务处理方式,太糟糕了!Java 发生了什么?! :)。

我知道这将引发巨大的讨论,但无论如何,我已经在我的项目中使用了一个非常好的 API,并且它足够稳定(它是 OSS,所以在真正信任 API 之前,您仍然需要对使用的每个版本进行压力测试):https ://github.com/jezhumble/javasysmon

JavaDoc: http: //jezhumble.github.io/javasysmon/,搜索类com.jezhumble.javasysmon.OsProcess,她会做的伎俩。希望它有所帮助,祝你好运。

于 2015-09-04T01:38:37.063 回答