为什么我的Java代码无法正确执行bash命令? [英] Why does my Java code execute bash command incorrectly?

查看:73
本文介绍了为什么我的Java代码无法正确执行bash命令?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使我的Java程序与Linux bash交互,但是出了点问题.我有一个简单的可执行文件prog,它从stdin读取一个整数并输出其平方.执行中

I am trying to make my Java program interact with Linux bash but something goes wrong. I have a simple executable prog that reads the one integer from stdin and outputs its square. Executing

echo 5 | ./prog

来自bash的

本身会在stdout中打印正确答案25但正在运行

from bash itself prints correct answer 25 in stdout but running

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.解决办法是什么?

unexpectedly gives 5 | ./prog. What is the solution?

推荐答案

Java exec无法运行这样的shell命令.如果要运行shell命令,则需要显式调用该shell;否则,您将无法运行该shell.例如

Java exec cannot run shell commands like that. If you want to run a shell command, you need to explicitly invoke the shell; e.g.

Process proc = run.exec(new String[]{"/bin/sh", "-c", "echo 5 | ./prog"});

有关Java使用此功能的更多详细信息,请阅读

For more details on what Java does with this, read the javadocs for exec(String) and exec(String[]). Note that these are "convenience methods", and you need to follow the chain of links to the underlying methods for a complete understanding of what the javadoc is saying.

如果您想了解有关Java处理方式的更多信息,请参见源代码...

If you want even more detail on how Java handles this, there is the source code ...

如果您想深入了解为什么Java 本身处理shell语法的原因,则可能需要深入研究UNIX/Linux系统的体系结构和哲学,以及分离应用程序,操作系统和命令外壳之间的关系.请注意,有无数个 different 外壳,每个外壳都有(可能)不同的规则,用于引用,参数拆分,重定向,管道等.大多数流行的shell都是相似的,但这只是事情的解决方法.

If you want to understand in depth why Java doesn't handle the shell syntax itself, you probably need to take a deep dive into the architecture and philosophy of UNIX / Linux systems, and the separation of concerns between application, operating system and command shell. Note that there are a myriad different shells, each with (potentially) different rules for quoting, argument splitting, redirection, pipes, etcetera. Most of the popular shells are similar, but that's just the way things panned out.

解决方案的说明:

  • 手动拆分命令的原因是exec(String)不会将命令正确拆分为单个命令和参数.不可以这是一个示例,其中在管道中有两个 命令.

  • The reason for splitting the command by hand is that exec(String) won't split the command into a single command and arguments correctly. It can't. This is an example where there are two commands in a pipeline.

使用"sh"的原因是……嗯……您需要一个shell来解析和处理shell命令行. Java的exec命令不支持shell语法...如javadoc所解释.

The reason for using "sh" is ... well ... you need a shell to parse and process a shell command line. Java's exec command does not support shell syntax ... as the javadoc explains.

-c"选项的用途由"man sh"解释.基本上,sh -c "a b c"的意思是使用'sh'运行命令行'a b c'".

The purpose of the "-c" option is explained by "man sh". Basically, sh -c "a b c" means "use 'sh' to run the command line 'a b c'".

FWIW,从技术上讲,仅使用Java即可构建和运行管道(即不依赖外部外壳),但通常不值得付出努力.您已经通过运行外部命令引入了平台依赖性,因此,以特定的shell命令和语法形式出现的额外依赖性不会使情况变得更糟.

FWIW, it is technically possible to construct and run a pipeline solely in Java (i.e. without relying on an external shell), but it is generally not worth the effort. You've already introduced a platform dependency by running external commands, so an extra dependency in the form of a specific shell command and syntax doesn't make things significantly worse.

这篇关于为什么我的Java代码无法正确执行bash命令?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆