如何将子进程stdout / stderr重定向到Java中的主进程stdout / stderr?

时间:2012-05-10 19:08:10

标签: java process

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

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

我的第一次尝试是:

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

但它不起作用。基于this answerthis answer,我已将代码替换为:

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

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

3 个答案:

答案 0 :(得分:15)

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

编辑。上面的答案对于java< 7.从javadoc 7开始,它似乎可以改为调用

processBuilder.redirectOutput(Redirect.INHERIT)

答案 1 :(得分:3)

这不是太糟糕。我最初说" easy"然后我意识到我必须编写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();
    }

答案 2 :(得分:1)

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