我正在尝试让我的 Java 程序与 Linux bash 交互,但出了点问题。我有一个简单的可执行文件 prog
,它从 stdin
读取一个整数并输出它的平方。执行中
echo 5 | ./prog
bash 本身在 stdout
中打印正确答案 25
但正在运行
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 | ./编
。解决方案是什么?
最佳答案
Java exec
无法运行这样的 shell 命令。如果要运行 shell 命令,则需要显式调用 shell;例如
Process proc = run.exec(new String[]{"/bin/sh", "-c", "echo 5 | ./prog"});
有关 Java 的更多详细信息,请阅读 exec(String)
的 javadocs和 exec(String[])
.请注意,这些是“便捷方法”,您需要遵循指向底层方法的链接链,才能完整理解 javadoc 所说的内容。
如果您想了解有关 Java 如何处理此问题的更多详细信息,请查看源代码...
如果您想深入了解为什么 Java 不 处理 shell 语法本身,您可能需要深入了解 UNIX/Linux 系统的体系结构和哲学,以及分离应用程序、操作系统和命令 shell 之间的关注点。请注意,有无数的 不同 shell,每个 shell 都有(可能)不同的引用、参数拆分、重定向、管道等规则。大多数流行的 shell 都是相似的,但这正是事情发展的方式。
解法说明:
手动拆分命令的原因是
exec(String)
不会将命令正确拆分为单个命令和参数。它不能。这是一个管道中有两个 命令的示例。使用“sh”的原因是……好吧……您需要一个 shell 来解析和处理 shell 命令行。 Java 的
exec
命令不支持 shell 语法……正如 javadoc 所解释的那样。“-c”选项的用途由“man sh”解释。基本上,
sh -c "a b c"
表示“使用‘sh’运行命令行‘a b c’”。
FWIW,仅在 Java 中构建和运行管道在技术上是可行的(即不依赖外部 shell),但通常不值得付出努力。您已经通过运行外部命令引入了平台依赖性,因此以特定 shell 命令和语法形式存在的额外依赖性不会使事情变得更糟。
关于java - 为什么我的 Java 代码无法正确执行 bash 命令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18424541/