java - ProcessBuilder:在不阻塞主线程的情况下转发已启动进程的标准输出和标准错误

标签 java processbuilder

我正在使用 ProcessBuilder 在 Java 中构建一个流程,如下所示:

ProcessBuilder pb = new ProcessBuilder()
        .command("somecommand", "arg1", "arg2")
        .redirectErrorStream(true);
Process p = pb.start();

InputStream stdOut = p.getInputStream();

现在我的问题如下:我想捕获该进程的标准输出和/或标准错误,并将其异步重定向到 System.out。我希望进程及其输出重定向在后台运行。到目前为止,我发现这样做的唯一方法是手动生成一个新线程,该线程将连续从 stdOut 读取,然后调用适当的 write() 方法System.out

new Thread(new Runnable(){
    public void run(){
        byte[] buffer = new byte[8192];
        int len = -1;
        while((len = stdOut.read(buffer)) > 0){
            System.out.write(buffer, 0, len);
        }
    }
}).start();

虽然这种方法行得通,但感觉有点脏。最重要的是,它为我提供了另一个线程来正确管理和终止。有没有更好的方法来做到这一点?

最佳答案

使用ProcessBuilder.inheritIO,它将子进程标准I/O的源和目标设置为与当前Java进程相同。

Process p = new ProcessBuilder().inheritIO().command("command1").start();

如果 Java 7 不是一个选项

public static void main(String[] args) throws Exception {
    Process p = Runtime.getRuntime().exec("cmd /c dir");
    inheritIO(p.getInputStream(), System.out);
    inheritIO(p.getErrorStream(), System.err);

}

private static void inheritIO(final InputStream src, final PrintStream dest) {
    new Thread(new Runnable() {
        public void run() {
            Scanner sc = new Scanner(src);
            while (sc.hasNextLine()) {
                dest.println(sc.nextLine());
            }
        }
    }).start();
}

子进程完成后线程会自动死亡,因为src会EOF。

关于java - ProcessBuilder:在不阻塞主线程的情况下转发已启动进程的标准输出和标准错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14165517/

相关文章:

java - 在 Process Builder 中切换用户

java - 取消 Eclipse 插件作业

java - spring boot主类,如何指定

Java 由 MySQL 触发器运行

java - 如何以正确的形式获取信息(Spring Boot)

java - 使用 Java 递归分解,处理 StackOverflow

java - 以编程方式修改 Spring bean

java - 如何从 Java 中的相对路径运行可执行文件

java - Process.exitValue() 和 Process.destroy() 功能

java - ProcessBuilder 和 ssh 调用远程命令