【问题标题】:Process started with ProcessBuilder stop supplying data以 ProcessBuilder 开始的进程停止提供数据
【发布时间】:2020-08-09 23:32:56
【问题描述】:

我需要在 windows 上运行 java 的 unix 程序。 unix 程序将文件名作为第一个参数,处理文件,并将处理后的文件返回到标准输出。

以下内容可在 CMD 控制台中完美运行:

wsl.exe /home/user/process /mnt/c/Users/user/input

它将 stdout 和 stderr 打印到控制台;或者我可以将标准输出重定向到一个重 1.2MB 的新文件中。

我想用 Java 做同样的事情。以下代码是最简化的版本

ProcessBuilder toCsv = new ProcessBuilder("wsl.exe", "/home/user/process", "/mnt/c/Users/user/input");
Process proc = toCsv.start();
try (InputStream is = proc.getInputStream()){
 for(int i=0; is.read() != -1; i++) {
   System.out.println(i);
 }
}

这总是在字节数 380927 上停止。调试器显示它在 FileInputStream.read 上停止

  • 我尝试使用重定向将标准输出发送到文件
  • 我尝试只读取标准错误
  • 我尝试使用 waitFor 在主线程上阅读不同的线程
  • 我尝试在没有 mainFor 的主线程上阅读不同的线程
  • 我尝试在不使用 Thread.sleep 而不是 waitFor 的情况下阅读
  • 我尝试将 "/bin/bash", "-c", exec+" "+execFile 传递给 ProcessBuilder
  • 我尝试使用 Runtime.exec 而不是 ProcessBuilder
  • 我试过"/bin/bash", "-c", "while :; do echo 1; done"。这实际上打破了 380k 字节的限制,并且像预期的那样无限增长。

发生了什么,我该如何解决?

附: unix 可执行文件的源代码是here,但我认为它不是很有用,因为它可以通过 CMD 运行

【问题讨论】:

    标签: java process windows-subsystem-for-linux processbuilder


    【解决方案1】:

    我在打字时找到了答案。显然,您必须以某种方式同时处理 STDERR 和 STDOUT 流,它们不会消失。如果你只读取其中一个而忽略另一个,最终被忽略的缓冲区会变得太大并阻塞,直到它被清空。

    所以添加以下代码解决了它

    new Thread( () -> {
         try (InputStream es = csvBuilder.getErrorStream() ){
                IOUtils.skip(es, Long.MAX_VALUE);
         } catch (IOException e) {
                throw new RuntimeException(e);
         }
    }).start();
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-25
      • 2021-04-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多