[英]Java - kill external process with TimerTask
我实现了一个方法,其中使用 processBuilder 调用外部程序。 如果外部进程花费的时间超过 5 秒(出于测试原因),我想停止该任务。
当我使用 process.exec() 时,实现工作正常。 但不是 processBuilder.start()
我已经阅读了一些帖子,但它似乎不起作用,因为我无法弄清楚我错过了什么。
方法:
ProcessBuilder processBuilder = new ProcessBuilder("/.../test.bat -a -b -c").redirectErrorStream(true);
Process process = processBuilder.start();
Timer t = new Timer();
TimerTask killer = new TimeoutProcessKiller(process);
t.schedule(killer, 5 * 1000);
BufferedReader lineReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
lineReader.lines().forEach(str -> LOGGER.log(Level.INFO, str));
int lExitCode = process.waitFor();
if (lExitCode == 0) {
LOGGER.log(Level.INFO, "Process finished successful.");
} else {
LOGGER.log(Level.INFO, "Process finished not successful.");
}
killer.cancel();
超时进程杀手
public class TimeoutProcessKiller extends TimerTask {
private Process p;
public TimeoutProcessKiller(Process p) {
this.p = p;
}
public void run() {
p.destroy();
}
}
谢谢你的任何建议。
您的问题很可能是因为您的批处理脚本已经启动了子进程,这些子进程在您的任务破坏了父进程后仍在运行。 更改TimeoutProcessKiller.run()
方法以打印出descendants
(子进程及其所有子进程),然后也将其杀死。
以下将打印每个尝试杀死它们的PID:
public void run() {
System.out.println("destroying "+p);
p.destroy();
System.out.println("destroying descendants");
p.descendants().peek(System.out::println).forEach(ProcessHandle::destroy);
System.out.println("destroyed "+p);
}
您从Runtime.exec()
到ProcessBuilder
所做的更改不是原因 - 因为Runtime.exec()
是对ProcessBuilder
的调用。 如果您不使用 STDOUT stream ,后代的问题就会消失(这不是一件明智的事情,因为这会冻结进程),所以您很可能在从Runtime.exec()
交换之后添加了BufferedReader lineReader...
?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.