【问题标题】:Java Process: read stdout and stderr of a subprocess in a single threadJava进程:在单个线程中读取子进程的stdout和stderr
【发布时间】:2016-10-08 10:49:52
【问题描述】:

假设我在 Java 中启动了一个子进程,它可能会写入 stdout 和 stderr:

Process subprocess = Runtime.getRuntime().exec(…);

我想读取它所有的标准输出和标准错误;或者直接忽略它们。

  1. 如果我这样做:

    readAllFrom(subprocess.getInputStream()); //stdout is getInputStream, weird!
    readAllFrom(subprocess.getErrorStream()); //stderr
    

    ...如果子进程首先尝试将数据输出到 stderr 并因此在该点阻塞,它会卡住。

    如果我这样做:

    while (…) {
        readLineFrom(subprocess.getInputStream());
        readLineFrom(subprocess.getErrorStream());
    }
    

    ……实际上,风险似乎是一样的。

  2. 如果我这样做:

    while (…) {
        nonblockingReadFrom(subprocess.getInputStream());
        nonblockingReadFrom(subprocess.getOutputStream());
    }
    

    nonblockingReadFrom 可以是这样的:

    … nonblockingReadFrom(InputStream stream) {
        byte[] buffer = new byte[…];
        stream.read(buffer, 0, Math.min(stream.available(), buffer.length));
        …
    }
    

    …如果子进程输出数据时有一些暂停,这将导致无用的 100%-CPU 负载。

  3. 当然,我可以创建单独的线程。像这里的东西(12)。但我的问题是关于在同一个线程中做所有事情。可能需要类似 select system call 的 Java 接口。

所以,问题是:是否可以在不使用额外线程或临时文件的情况下,在 Java 中正确处理 java.lang.Process 类型子进程的 stdout 和 stderr?

【问题讨论】:

  • 你见过这个 - stackoverflow.com/questions/14165517/… 吗?
  • @GhostCat,似乎无关。接受的答案使用流 gobblers,这是多线程解决方案。 Evgeniy Dorofeev 的回答只是相应地将子进程的 stdout 和 stderr 重定向到主进程的 stdout 和 stderr,这不是我的目标。
  • 是否可以将标准错误重定向到标准输出?如果是这样,this question 可能会有所帮助。
  • 请查看此链接stackoverflow.com/questions/5711084/…。它可能对您的目的有所帮助。
  • @LukeWoodward,当然没有。

标签: java process runtime.exec


【解决方案1】:

不,您不能只从 Process 返回的 InputStream 创建 SelectableChannel,这是 Java api 限制 AFAICT。

【讨论】:

  • “我认为您可以等待进程终止,然后检查两个流。”
  • 是的,如果您不使用流,它将阻塞(您可以通过运行cat /dev/urandom 子进程自己尝试)。这就是为什么如果子进程要产生大量输出并且您不想在读取时阻塞父进程时应该使用线程。
  • 那么,请删除答案的第二部分(IMO 让读者感到困惑),这样我就无法接受(如果我理解正确,第一部分的意思是 不,从 Java 8 开始,目前是不可能的。)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-16
  • 2016-12-21
  • 2023-04-06
  • 2013-08-26
  • 1970-01-01
  • 2011-07-07
  • 2020-06-23
相关资源
最近更新 更多