bash Java exec() 不返回管道连接命令的预期结果
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2088917/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java exec() does not return expected result of pipes' connected commands
提问by Pawka
I'm calling command line programs connected by pipes. All this works on Linux for sure.
我正在调用由管道连接的命令行程序。所有这些都可以在 Linux 上运行。
My method:
我的方法:
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;
}
If I'm calling some cat file | grep asd, I'm getting the expected result. But not all commands works correctly. For example with this:
如果我正在调用一些cat 文件 | grep asd,我得到了预期的结果。但并非所有命令都能正常工作。例如与此:
cat /proc/cpuinfo | wc -l
or this:
或这个:
cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr(, 2, length())}
the method will return null. I'm guessing this problem depends on output formatting commands like head, tail, wc, etc. How I can work around this problem and get the final result of the output?
该方法将返回 null。我猜这个问题取决于输出格式命令,如head、tail、wc等。我如何解决这个问题并获得输出的最终结果?
采纳答案by Pawka
Still didn't found proper solution to execute piped commands with Runtime.exec, but found a workaround. I've simply wrote these scripts to separate bash files. Then Runtime.exec calls these bash scripts and gets expected result.
仍然没有找到使用 Runtime.exec 执行管道命令的正确解决方案,但找到了解决方法。我只是编写了这些脚本来分隔 bash 文件。然后 Runtime.exec 调用这些 bash 脚本并得到预期的结果。
回答by Brian Agnew
The pipe (like redirection, or >) is a function of the shell, and so execing directly from Java won't work. You need to do something like:
管道(如重定向或>)是 shell 的一个函数,因此直接从 Java 执行是行不通的。您需要执行以下操作:
/bin/sh -c "your | piped | commands | here"
which executes a shell process with the command line (including pipes) specified after the -c(in quotes).
它使用在-c(引号中)之后指定的命令行(包括管道)执行 shell 进程。
Note also that you have to consume stdoutand stderrconcurrently, otherwise your spawned process will block waiting for your process to consume the output (or errors). More info here.
还需要注意的是,你必须消耗stdout和stderr并发,否则你的衍生进程将阻止等待你的过程中要消耗的输出(或错误)。更多信息在这里。
回答by leedm777
The quick-and-dirty thing to do would be:
快速而肮脏的事情是:
command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'"
Normally, you'll have to watch out for shell injection (i.e. someone sneaks "; rm -rf /;"into the command). But that's only an issue if part of the command can be supplied from some other user input.
通常,您必须注意 shell 注入(即有人潜入"; rm -rf /;"命令)。但这只是一个问题,如果命令的一部分可以从其他一些用户输入中提供。
The slow and painful approach would be to do the Bash piping yourself in Java. If you go down this road, you'll find out all the wonderful things that Bash gives youthat's not directly available from Process.exec(pipes, redirection, compound commands, variable expansion, arithmetic evaluation, ...).
缓慢而痛苦的方法是自己在 Java 中执行 Bash 管道。如果你沿着这条路走下去,你会发现Bash 为你提供的所有美妙的东西,这些东西不能直接从Process.exec(管道、重定向、复合命令、变量扩展、算术评估等)获得。
- Parse the command for
|characters. Be sure to watch out for||and quoted strings. - Spawn a new
Processfor every piped command. - Create
Threads that read the output from one command and write it to the input of the next command.
- 解析
|字符的命令。一定要注意||和引用的字符串。 Process为每个管道命令生成一个新命令。- 创建
Thread从一个命令读取输出并将其写入下一个命令的输入的 s。
回答by matt b
It might be a good idea to check the error stream of the Processas well.
检查进程的错误流也可能是一个好主意。
回答by stolen_leaves
Probably a little too late but for others looking for a solution, try this...
可能有点太晚了,但对于其他正在寻找解决方案的人来说,试试这个......
String[] cmd = {
"/bin/sh",
"-c",
"cat /proc/cpuinfo | wc -l"
};
Process process = Runtime.getRuntime().exec(cmd);
All the best..
祝一切顺利..

