Java 进程获取输出并设置超时
Java Process get output and set timeout
如何在设置超时值时获取进程的输出?
我目前正在使用 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);
}
正如@EJP 建议的那样,您可以使用不同的线程来捕获流或使用 ProcessBuilder
或从您的命令重定向到文件。
以下是我认为您可以使用的 3 种方法。
对流使用不同的线程。
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());
使用 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")));
在命令中使用重定向运算符将输出和错误重定向到文件,然后从文件读取。
Here 是一个很好的博客,解释了不同的处理方式 Runtime.Exec
如何在设置超时值时获取进程的输出?
我目前正在使用 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);
}
正如@EJP 建议的那样,您可以使用不同的线程来捕获流或使用 ProcessBuilder
或从您的命令重定向到文件。
以下是我认为您可以使用的 3 种方法。
对流使用不同的线程。
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());
使用
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")));
在命令中使用重定向运算符将输出和错误重定向到文件,然后从文件读取。
Here 是一个很好的博客,解释了不同的处理方式 Runtime.Exec