11

在其他语言(如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);

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

4

3 回答 3

18

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

编辑。上面的答案对于 java < 7 是正确的。从 javadoc 的 7 开始,它看起来可以改为调用

processBuilder.redirectOutput(Redirect.INHERIT)
于 2012-05-10T19:18:04.750 回答
3

这还不错。我最初说“简单”,然后我意识到我必须编写 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();
    }
于 2014-03-28T17:15:46.353 回答
1

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

于 2012-05-10T19:19:53.543 回答