【问题标题】:How to redirect child process stdout/stderr to the main process stdout/stderr in Java?java - 如何将子进程stdout/stderr重定向到Java中的主进程stdout/stderr?
【发布时间】:2012-05-10 19:08:09
【问题描述】:

在其他语言中(如 bashPython),当我们生成子进程时,这个新进程将从父进程继承 stdout 和 stderr。这意味着子进程的任何输出都将打印到终端以及父进程的输出。

我们如何在 Java 中实现相同的行为?

我的第一次尝试是:

proc = Runtime.getRuntime().exec(cmd);

但这行不通。基于this answerthis answer,我将代码替换为:

ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectOutput(System.out);
pb.redirectError(System.err);

但这甚至无法编译,因为参数与预期的方法参数不兼容。

【问题讨论】:

    标签: java process


    【解决方案1】:

    您需要读取您创建的进程的输出和错误流,并将输出写入您想要的位置(在您的情况下为 System.out 和 System.err)。

    编辑。上面的答案对于 java

    processBuilder.redirectOutput(Redirect.INHERIT)
    

    【讨论】:

    • 你的意思是我需要实现一个循环,只保持从一个流读取并写入另一个流?抱歉,不可行。工作量太大(可能需要在新线程中运行,并且会引入很多可能的错误点)。
    • 可行与否这曾经是必需的。我刚刚检查了 java 7 api,它看起来已经解决了 - 你现在可以调用 redirectOutput 传入 Redirect.INHERIT ,它看起来可以实现你想要的。
    【解决方案2】:

    这还不错。我最初说“简单”,然后我意识到我必须编写 InputStreamConsumer:

    public static class InputStreamConsumer extends Thread {
    
        private InputStream is;
    
        public InputStreamConsumer(InputStream is) {
            this.is = is;
        }
    
        @Override
        public void run() {
    
            try {
                int value = -1;
                while ((value = is.read()) != -1) {
                    System.out.print((char)value);
                }
            } catch (IOException exp) {
                exp.printStackTrace();
            }
        }
    }
    
    private void captureOutput(Process p) {
    
        InputStreamConsumer stdout;
        InputStreamConsumer errout;
    
        errout = new InputStreamConsumer(p.getErrorStream());
        stdout = new InputStreamConsumer(p.getInputStream());
        errout.start();
        stdout.start();
    }
    

    ....在类似...的地方运行

        ProcessBuilder pb = new ProcessBuilder("cmd.exe", "/D", "/C", myCommand, parm, parm...);
        try {
            System.out.println("Start "+myCommand);
            Process myProcess = pb.start();
            captureOutput(myProcess);
    
            int returnCode = myProcess.waitFor();
            System.out.println("myProcess: return code : "+returnCode);
        }
        catch (IOException e) {
            e.printStackTrace();
        }
    

    【讨论】:

    • 其他的对我不起作用,除了在 IDE 中。这个做了,谢谢。
    • 看起来不错——但我们必须使用这种自我实现的代码吗? Java 不支持将 STDERR 重定向到 STDOUT,然后从一个输入流中读取它们的组合?
    【解决方案3】:

    这当然是可能的。当 fork 设置为 true 时,Ant Java 任务会执行此操作。我不记得所有的细节,但快速浏览一下,似乎大部分魔法都在PumpStreamHandler 中。您可以尝试从中寻找一些灵感。

    【讨论】:

    • 实际上比这更容易,但仅适用于 1.7,您似乎正在使用它,因为您使用的是 ProcessBuilder.redirectOutput() 是做 pb.redirectOutput(Redirect.INHERIT)。虽然我自己从来没有这样做过。
    猜你喜欢
    • 2012-07-14
    • 2015-08-18
    • 1970-01-01
    • 1970-01-01
    • 2011-07-18
    • 2014-07-22
    • 1970-01-01
    • 2022-01-18
    • 2023-04-06
    相关资源
    最近更新 更多