我试图让我的 Java 程序与 Linux bash 交互,但出了问题。我有一个简单的可执行文件prog
从中读取一个整数stdin
并输出其平方。执行中
echo 5 | ./prog
从 bash 本身打印正确答案25
in stdout
但运行
import java.io.*;
public class Main {
public static void main(String[] args) throws InterruptedException, IOException {
Runtime run = Runtime.getRuntime();
Process proc = run.exec("echo 5 | ./prog");
proc.waitFor();
BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream()));
while(br.ready())
System.out.println(br.readLine());
}
}
出乎意料地给出5 | ./prog
。解决办法是什么?
Java exec
无法运行这样的 shell 命令。如果要运行 shell 命令,则需要显式调用 shell;例如
Process proc = run.exec(new String[]{"/bin/sh", "-c", "echo 5 | ./prog"});
有关 Java 对此做什么的更多详细信息,请阅读 javadocsexec(String) http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec%28java.lang.String%29 and exec(String[]) http://docs.oracle.com/javase/7/docs/api/java/lang/Runtime.html#exec%28java.lang.String%5B%5D%29。请注意,这些是“便捷方法”,您需要遵循底层方法的链接链才能完整理解 javadoc 的内容。
如果您想了解有关 Java 如何处理此问题的更多详细信息,请参阅源代码...
如果你想深入了解Java为什么doesn't处理 shell 语法本身,您可能需要深入研究 UNIX/Linux 系统的体系结构和原理,以及应用程序、操作系统和命令 shell 之间的关注点分离。请注意,有无数不同的shell,每个都有(可能)不同的引用、参数分割、重定向、管道等规则。大多数流行的 shell 都是相似的,但这就是事情的发展方式。
解决方案说明:
手动分割命令的原因是exec(String)
不会将命令拆分为单个命令和参数正确。不可以。这是一个例子,其中有two管道中的命令。
使用“sh”的原因是……嗯……你need用于解析和处理 shell 命令行的 shell。爪哇的exec
命令不支持 shell 语法...正如 javadoc 所解释的那样。
“-c”选项的用途由“man sh”解释。基本上,sh -c "a b c"
意思是“使用‘sh’运行命令行‘a b c’”。
FWIW,在技术上可以仅用 Java 构建和运行管道(即不依赖外部 shell),但通常不值得付出努力。您已经通过运行外部命令引入了平台依赖性,因此特定 shell 命令和语法形式的额外依赖性不会使情况变得更糟。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)