java - ProcessBuilder 启动的进程停止提供数据

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

我需要从在Windows上运行的java运行一个unix程序。 unix 程序将文件名作为第一个参数,处理该文件,并在 stdout 上返回处理后的文件。

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

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

它将 stdout 和 stderr 打印到控制台;或者我可以将 stdout 重定向到一个新文件,该文件大小为 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 上停止

  • 我尝试使用重定向将标准输出发送到文件
  • 我尝试只读取 stderr
  • 我尝试在主线程上使用 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 运行

最佳答案

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

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

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

关于java - ProcessBuilder 启动的进程停止提供数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61441484/

相关文章:

Python3.4 错误-无法启用可执行堆栈,因为共享对象需要 : Invalid argument

java - 获取任意java方法的委托(delegate)函数

php - PHP/Python 中的死人开关

module - Erlang中的模块和进程之间有什么关系

c++ - 从 WSL 构建 Linux 应用程序失败,错误为 : file format not recognized; treating as linker script

django - 从在 WSL 上运行的 django 连接到在 Windows 上运行的 Postgres

java - 我可以在单线程中使用两个套接字吗?

java - 在 Times-New-Roman 字体中使用 Itextpdf 的度数符号

java - 实体中的 JPA 外键

c++ - 查找进程从哪里运行