Java进程获取输出并设置超时
Posted
技术标签:
【中文标题】Java进程获取输出并设置超时【英文标题】:Java Process get output and set timeout 【发布时间】:2017-05-20 08:49:36 【问题描述】:如何在设置超时值时获取进程的输出?
我目前正在使用 apache commons io utils 从进程的标准和错误输出中创建一个字符串。
下面的代码(与 cmets 一样)适用于终止的进程。但是,如果进程没有终止,主线程也不会终止!
如果我取消注释掉注释代码,而是注释掉 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);
【问题讨论】:
您需要在单独的线程中获取输出。 【参考方案1】:正如@EJP 建议的那样,您可以使用不同的线程来捕获流或使用ProcessBuilder
或从您的命令重定向到文件。
以下是我认为您可以使用的 3 种方法。
为 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());
使用 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
的不同方法
【讨论】:
在你的第一个例子中。您使用 threadPool.shutdown()。 javadoc 有点混乱。 启动有序关闭,其中执行先前提交的任务,但不会接受新任务 vs 此方法不等待先前提交的任务完成执行。使用 awaitTermination 来做到这一点。 那么这会提前终止线程吗? @IrxwShutdown
只会告诉执行者停止接受新请求。但是,现有/提交的任务将继续运行而不会中断。此外,呼叫Shutdown
不会阻止您等待所有提交的任务完成的呼叫。为确保您希望等待所有任务完成,请调用Shutdown
,然后调用AwaitTermination
。有 ShutdownNow
尽最大努力通过主要中断等待/运行的线程来做到这一点,但即使这样也不能保证提交的任务将被杀死/中断。
谢谢,我将“不等待”理解为“它会杀死它”。但它只是说它没有阻塞并等待它完成。但它仍然优雅。以上是关于Java进程获取输出并设置超时的主要内容,如果未能解决你的问题,请参考以下文章
[Java]_[初级]_[如何调用外部命令获取输出并设置它的超时退出]