Java exec()不会返回pipe道连接命令的预期结果

我正在调用通过pipe道连接的命令行程序。 所有这些都可以在Linux上运行。

我的方法:

protected String execCommand(String command) throws IOException { String line = null; if (command.length() > 0) { Process child = Runtime.getRuntime().exec(command); InputStream lsOut = child.getInputStream(); InputStreamReader r = new InputStreamReader(lsOut); BufferedReader in = new BufferedReader(r); String readline = null; while ((readline = in.readLine()) != null) { line = line + readline; } } return line; } 

如果我打电话给一些猫文件| grep asd ,我得到了预期的结果。 但并不是所有的命令都能正常工 例如:

 cat /proc/cpuinfo | wc -l 

或这个:

 cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr($2, 2, length($2))} 

该方法将返回null。 我猜这个问题取决于输出格式化命令,如尾巴厕所等我怎样才能解决这个问题,并得到最终的结果?

管道(如重定向,或> )是shell的一个函数,所以直接从Java中直接执行是行不通的。 您需要执行以下操作:

 /bin/sh -c "your | piped | commands | here" 

它使用-c (在引号中)之后指定的命令行(包括管道)执行shell进程。

还要注意,你必须同时使用stdoutstderr ,否则你的产生的进程会阻塞等待你的进程使用输出(或错误)。 更多信息在这里 。

每个使用Runtime.exec的人都应该阅读这个 。

仍然没有找到适当的解决方案来执行与Runtime.exec管道命令,但找到了一种解决方法。 我只是写了这些脚本分开bash文件。 然后Runtime.exec调用这些bash脚本并获得预期的结果。

检查Process的错误流也是一个好主意。

这个快速而肮脏的事情是:

 command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'" 

通常情况下,你将不得不注意shell注入(即有人偷偷"; rm -rf /;"到命令中)。 但是这只是一个问题,如果命令的一部分可以从其他用户输入提供。

缓慢而痛苦的做法是自己用Java做Bash。 如果你顺着这条路走,你会发现Bash给你的所有美妙的东西都不能从Process.exec直接获得(管道,重定向,复合命令,可变扩展,算术评估…)。

  1. 解析|的命令 字符。 一定要注意|| 并引用字符串。
  2. 为每个管道命令产生一个新的Process
  3. 创建Thread ,读取一个命令的输出并将其写入下一个命令的输入。

可能有点晚了,但对于其他人寻找解决方案,试试这个…

 String[] cmd = { "/bin/sh", "-c", "cat /proc/cpuinfo | wc -l" }; Process process = Runtime.getRuntime().exec(cmd); 

祝一切顺利..