java - 为什么我的 Java 代码无法正确执行 bash 命令?

标签 java linux bash pipe

我正在尝试让我的 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/

相关文章:

java - 在 jFreechart 中设置项目形状大小

java - 将属性封装在属性/上下文类中

linux - 更改 cd 默认目录 (bash)

java,apache poi,空点错误

java - 如何根据 Word 文档大小 Apache-POI 自动调整表格并将表格居中对齐?

ruby-on-rails - Ruby: "gem install bundler"未安装 bundler

linux - 你能帮我使用 smbclient 从 Ubuntu 访问 Mac SMB 共享吗? (NT_STATUS_ACCESS_DENIED 错误)

linux - Makefile目标颜色输出

linux - 在 bash 中打印字母表

java - 创建 bash 命令 java