Java Process 获取输出并设置超时

way*_*way 2 java multithreading inputstream process

如何在设置超时值时获取进程的输出?

我目前正在使用 apache commons io utils 从进程的标准和错误输出创建一个字符串。

下面的代码按原样(带有注释)适用于终止的进程。但是,如果进程没有终止,主线程也不会终止!

如果我取消注释掉已注释的代码,而是注释掉 process.waitfor(),该方法将正确销毁非终止进程。但是,对于终止进程,无法正确获得输出。似乎一旦 waitfor() 完成,我就无法获得进程的输入和错误流?

最后,如果我尝试将注释部分移动到 process.waitfor() 当前所在的位置,删除 process.waitfor() 并取消注释注释部分,那么对于非终止进程,主线程也不会停止。这是因为 process.waitfor(15, ...) 永远不会到达。

private static Outputs runProcess(String command) throws Exception {
    Process process = Runtime.getRuntime().exec(command);

    // if (!process.waitFor(15, TimeUnit.SECONDS)) {
    // System.out.println("Destroy");
    // process.destroy();
    // }

    // Run and collect the results from the standard output and error output
    String stdStr = IOUtils.toString(process.getInputStream());
    String errStr = IOUtils.toString(process.getErrorStream());

    process.waitFor();

    return new Outputs(stdStr, errStr);
}
Run Code Online (Sandbox Code Playgroud)

Ban*_*ore 6

正如@EJP 建议的那样,您可以使用不同的线程来捕获流,或者使用ProcessBuilder或重定向到您的命令中的文件。
以下是我认为您可以使用的 3 种方法。

  1. 为 Streams 使用不同的线程。

    Process process = Runtime.getRuntime().exec("cat ");
    
    ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2);
    
    Future<String> output = newFixedThreadPool.submit(() -> {
        return IOUtils.toString(process.getInputStream());
    });
    Future<String> error = newFixedThreadPool.submit(() -> {
        return IOUtils.toString(process.getErrorStream());
    });
    
    newFixedThreadPool.shutdown();
    
    // process.waitFor();
    if (!process.waitFor(3, TimeUnit.SECONDS)) {
        System.out.println("Destroy");
        process.destroy();
    }
    
    System.out.println(output.get());
    System.out.println(error.get());
    
    Run Code Online (Sandbox Code Playgroud)
  2. 使用 ProcessBuilder

    ProcessBuilder processBuilder = new ProcessBuilder("cat")
            .redirectError(new File("error"))
            .redirectOutput(new File("output"));
    
    Process process = processBuilder.start();
    
    // process.waitFor();
    if (!process.waitFor(3, TimeUnit.SECONDS)) {
        System.out.println("Destroy");
        process.destroy();
    }
    
    System.out.println(FileUtils.readFileToString(new File("output")));
    System.out.println(FileUtils.readFileToString(new File("error")));
    
    Run Code Online (Sandbox Code Playgroud)
  3. 在命令中使用重定向运算符将输出和错误重定向到文件,然后从文件中读取。

是一个很好的博客,它解释了不同的处理方式Runtime.Exec