【问题标题】:How to use Pipe Symbol through exec in Java [duplicate]如何在Java中通过exec使用管道符号[重复]
【发布时间】:2011-11-05 19:02:32
【问题描述】:

我正在使用以下代码来获取系统中运行的所有进程的详细信息:

Process p = Runtime.getRuntime().exec("ps aux");
BufferedReader stdInput = new BufferedReader(new 
             InputStreamReader(p.getInputStream()));
BufferedReader stdError = new BufferedReader(new 
             InputStreamReader(p.getErrorStream()));

我想用管道符号过滤ps aux,所以我用这个:

Process p = Runtime.getRuntime().exec("ps aux | grep java");

它进入 ErrorStream。后来我注意到管道符号 (|) 在 Java 中用作按位包含 OR 运算符。所以我在管道符号前面使用了反斜杠,如下所示:

Process p = Runtime.getRuntime().exec("ps aux \\| grep java"); 

但它再次进入 ErrorStream。如何在 Java 中通过 exec 运行 ps aux | grep java

【问题讨论】:

  • 澄清一下,按位或运算符| 不会在字符串中解释,因此您不需要转义它。

标签: java exec pipe


【解决方案1】:

抱歉,我不知道如何正确地将结果从一个命令传递到另一个命令,但如果您想要的只是 Java 进程,JDK 附带了一个名为 jps 的程序,它正是这样做的。试试这个:

jps -l

【讨论】:

  • 感谢您的回复。我尝试了该命令,它会生成包含 PID、进程名称的列表。我希望得到 PID %CPU %MEM VSZ RSS TTY & COMMAND。
【解决方案2】:

管道是一个 shell 功能 - 您不是在使用 shell,而是在执行一个进程 (ps)。

但实际上,您为什么要这样做?你说的是:

“执行 ps,然后将其输出通过管道传输到另一个程序 (grep) 并让它提取我需要的内容”

您只需要从ps 的输出中提取您想要的内容。使用Matcher 并只注意InputStream 中包含java 的行

http://download.oracle.com/javase/6/docs/api/java/util/regex/Matcher.html

【讨论】:

  • 感谢您的回复。当我使用 Runtime.getRuntime().exec("ps aux") 时,需要时间来处理来自 InputStream 的所有行。所以我认为 Runtime.getRuntime().exec("ps aux | grep java") 将只是我的工作。如果我再次使用 Matcher,则需要时间来处理线路。还有其他使用管道的方法吗?
  • Matcher 处理行确实不应该比shell 必须执行另一个进程并将ps 的输出通过管道传递给它花费更多的时间。话虽这么说......我认为你可以执行一个shell,比如/bin/bash -c ps aux |grep java
【解决方案3】:
  1. 在调用 exec 时,您需要将命令与其参数分开,例如 .exec(new String[] { "ps", "aux" })不是 exec("ps aux"))。当需要传递参数时,需要调用 String[] 版本——String[] 的第一个元素是命令,其余的是参数。

  2. 您需要将第一个命令的输出流的内容发送到第二个命令的输入流。我使用Apache commons IOUtils 轻松做到了这一点。

  3. 必须关闭grep调用的输入流,否则会挂起等待输入结束。

有了这些改变,这段代码就可以做你想做的事了:

import org.apache.commons.io.IOUtils;

public static void main(String[] args) throws Exception
{
    Process p1 = Runtime.getRuntime().exec(new String[] { "ps", "aux" });
    InputStream input = p1.getInputStream();
    Process p2 = Runtime.getRuntime().exec(new String[] { "grep", "java" });
    OutputStream output = p2.getOutputStream();
    IOUtils.copy(input, output);
    output.close(); // signals grep to finish
    List<String> result = IOUtils.readLines(p2.getInputStream());
    System.out.println(result);
}

【讨论】:

  • 单线程时有死锁危险吗?可以使用 commons-exec 中的PumpStreamHandler
  • 公平评论。我试图使这一点尽可能简单,以说明重要的部分。注意:在单线程环境中可能会死锁。
【解决方案4】:

好吧,如果你想在你执行的进程中使用管道,那么你需要启动一个像 bash 这样的 shell,然后在命令行上给那个 shell 提供 ps 和 grep:

bash -c "echo $PATH"

试试这个来理解我的意思,然后使用这个:

bash -c "ps axu | grep PATTERN"

了解您需要如何设置 java.runtime.Process。

我没有尝试过,但我认为是这样的:

Process p = Runtime.getRuntime().exec(new String[] { "bash", "-c", "ps axu | grep PATTERN" });

希望对您有所帮助;D

【讨论】:

  • 嘿,效果很好!谢谢!
  • 这对我不起作用......在阅读this之后,我最终决定使用 pgrep 而不是 grep
猜你喜欢
  • 2016-07-25
  • 2012-06-03
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 2014-03-16
  • 1970-01-01
  • 2011-10-04
相关资源
最近更新 更多