简体   繁体   English

如何在 Java 中捕获所有 Bash 输出

[英]How to capture all Bash output in Java

I already have Java code that can handle all the output from stdout and stderr, and that all works fine.我已经有了可以处理 stdout 和 stderr 的所有输出的 Java 代码,而且一切正常。 It uses getInputStream() and getErrorStream();它使用 getInputStream() 和 getErrorStream();

If I enter a command like this in a Bash terminal:如果我在 Bash 终端中输入这样的命令:

export ANDROID_HOME=/usr/local/bin/android-sdk-linux;export PATH=${PATH}:/usr/local/bin/gradle-1.8/bin;cd /var/local/android/dev/GradleHelloWorld;gradle clean

It gets extra output like:它获得额外的输出,如:

> Loading

>Loading Resolving dependencies ...

>Building

Until it gets the regular "end" output:直到它获得常规的“结束”输出:

:clean UP-TO-DATE

BUILD SUCCESSFUL

Total time: 2 mins 37.424 secs

But after trying many different combinations of, the below, with and without the "-c":但是在尝试了下面的许多不同组合后,有和没有“-c”:

processBuilder = new ProcessBuilder("bash", "-c", sCmd);

proc = rt.exec(new String[] {"/bin/bash", "-c", commandS});

I know those are pretty much the same, but you get the idea.我知道这些几乎相同,但你明白了。 It only shows the "end" result, and not any of the other output before it.它只显示“最终”结果,而不显示它之前的任何其他输出。

For Windows I can get all the output with no problem, using:对于 Windows,我可以毫无问题地获得所有输出,使用:

proc = rt.exec("cmd.exe");

and the command string.和命令字符串。

I don't know that much about Bash, so is there any other options I can try, or a different Java statement I can use to try to capture all the output using Java?我对 Bash 不太了解,所以我可以尝试其他任何选项,或者我可以使用不同的 Java 语句来尝试使用 Java 捕获所有输出吗?

Update:更新:

I'm already doing this (most of the code):我已经这样做了(大部分代码):

while ( true )
{

    if ( error_is.available() > 0 ) // Check Error Stream..
    {
        iBytesRead = error_is.read(tempBuf, 0, iTmpLength);
        if ( iBytesRead == -1 )
        {
             break;
        }

        baos.write(tempBuf, 0, iBytesRead);
   }
   else if ( out_is.available() > 0 )   // Check Output Stream..
   {
        iBytesRead = out_is.read(tempBuf, 0, iTmpLength);
        if ( iBytesRead == -1 )
        {
            break;
        }

        baos.write(tempBuf, 0, iBytesRead);
   }
}

It works fine in Windows using cmd.exe so I know it works, and it gets everything, but for Linux users, I have to use Bash, and I'm not getting some of the output, so that's my question..它在 Windows 中使用 cmd.exe 运行良好,所以我知道它可以工作,并且可以获取所有内容,但是对于 Linux 用户,我必须使用 Bash,但我没有得到一些输出,所以这就是我的问题。

You can use InputStreamReader in conjunction with BufferedReader to get the output of the command: 您可以将InputStreamReaderBufferedReader结合使用以获取命令的输出:

    ProcessBuilder pb = new ProcessBuilder("your-command");
    Process p = pb.start();
    InputStreamReader isr = new InputStreamReader(p.getInputStream());
    BufferedReader br = new BufferedReader(isr);

    String lineRead;
    while ((lineRead = br.readLine()) != null) {
        LOGGER.info(lineRead);
    }
    int rc = p.waitFor();
    return rc; // successful return code should be zero!

I've been struggling with this too.我也一直在为此苦苦挣扎。 After multiple readings of the source code for the unix implementation of Process at https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/unix/classes/java/lang/ProcessImpl.java it seems that the standard redirects will always swallow to a ProcessBuilder.NullInputStream :https://github.com/AdoptOpenJDK/openjdk-jdk11/blob/master/src/java.base/unix/classes/java/lang/ProcessImpl.java处多次阅读Process的 unix 实现的源代码后似乎标准重定向总是会吞下ProcessBuilder.NullInputStream

if (redirects[1] == Redirect.PIPE) {
                    std_fds[1] = -1;
}...

and

stdout = (fds[1] == -1 || forceNullOutputStream) ?
                         ProcessBuilder.NullInputStream.INSTANCE :
                         new ProcessPipeInputStream(fds[1]);

(The same code repeats for stdIn, stdOut and stdErr streams) (对 stdIn、stdOut 和 stdErr 流重复相同的代码)

The only workaround I have found, which feels very clumsy is to use a temp File:我发现的唯一解决方法是使用临时文件,感觉笨拙:

File stdOutTmp;  // create and destroy however you see fit
ProcessBuilder pb = ...;
pb.redirectOutput(ProcessBuilder.Redirect.to(stdOutTmp));
...

There are other static factory methods ( Redirect.appendTo(File) to append to an existing file rather than overwrite an existing file, and Redirect.from(File) for stdIn)还有其他静态工厂方法( Redirect.appendTo(File)附加到现有文件而不是覆盖现有文件,以及Redirect.from(File) for stdIn)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM