我已经在网上搜索,而process.waitFor() never returns这个问题表明它的stdout或stderr没有被读取的进程通常是一个问题。Process.waitFor即使stdout和stderr被读取也会挂起
我们使用ProcessBuilder
与redirectOutput
和redirectError
实现这一目标,我想我们应该是在安全方面,看看我们用它来执行过程如下方法:
public static void execute(String directory, long timeout, File out, File err, String... command) throws InterruptedException, IOException {
LOGGER.log(Level.INFO, String.format("executing command %s (%s)", Arrays.toString(command), timeout > 0 ? String.format("timeout = %,d[ms]", timeout) : "no timeout"));
ProcessBuilder builder = new ProcessBuilder();
builder.directory(new File(directory));
builder.command(command);
builder.redirectOutput(out);
if(out == err) {
builder.redirectErrorStream(true);
} else {
builder.redirectError(err);
}
long time = System.currentTimeMillis();
Process process = builder.start();
try {
LOGGER.log(Level.FINE, "waiting for process");
boolean exited = process.waitFor(timeout, TimeUnit.MILLISECONDS);
if(!exited) {
LOGGER.log(Level.WARNING, "timeout reached, trying to destroy ...");
exited = destroy(silent, process); // Helper method to destroy processes
}
long duration = System.currentTimeMillis() - time;
int exitValue = process.exitValue();
LOGGER.log(Level.INFO, "execution finished in " + duration + "[ms] => " + exitValue);
} catch (InterruptedException | Error | RuntimeException e) {
LOGGER.log(Level.SEVERE, "execution failed", e);
throw e;
}
}
然而,问题是,它挂起在process.waitFor(timeout, TimeUnit.MILLISECONDS)
调用,即使过程应该很容易在超时内完成。
测井输出是
Oct 07, 2017 12:39:55 AM at.ProcessExecutor execute
INFO: executing command [java, -Xmx8G, -XX:+UseG1GC, -XX:+CrashOnOutOfMemoryError, -jar, MetricCalc.jar] (timeout = 14,400,000[ms])
Oct 07, 2017 12:39:55 AM at.ProcessExecutor execute
FINE: waiting for process
(认识到,没有execution finished
线尚未写入)
的err
文件读取
... Things we write to std.err ...
Finished Metrics
和MetricCalc的主要方法如下所示
public static void main(String[] args) {
.... do some stuff ...
System.err.println("Finished Metrics");
}
这表明读取工作正常,Java程序的最后一行已经执行并且进程应该终止。
任何人有一个想法,为什么进程不会终止/它仍然挂在Process.waitFor()
?
*“......并且该流程应该已经终止。”* - 假定子流程按照您的预期工作。检查子进程是否实际终止;例如使用“ps -efl”或类似的。 –
@StephenC:我仍然可以使用'ps -efl | grep“java -Xmx8G”',表示它没有终止。 然而,我不知道为什么这是这样的情况,因为MetricCalc的最后一行代码(作为进程运行的Java程序)已经执行... –
哦,它刚刚出现在我的脑海里:可能是MetricCalc有一些非deamon线程正在运行,从而阻止应用程序终止...我将不得不测试这... –