简体   繁体   English

Java - 使用 TimerTask 杀死外部进程

[英]Java - kill external process with TimerTask

I implemented a method, where an external program is called with a processBuilder.我实现了一个方法,其中使用 processBuilder 调用外部程序。 If the external process takes longer than 5 seconds (for test reasons) I want to stop that task.如果外部进程花费的时间超过 5 秒(出于测试原因),我想停止该任务。

The implementation works fine when I use process.exec().当我使用 process.exec() 时,实现工作正常。 but not with processBuilder.start()但不是 processBuilder.start()

I have read some posts but it does not seem to work, since I can't not figure out what I'm missing.我已经阅读了一些帖子,但它似乎不起作用,因为我无法弄清楚我错过了什么。

Method:方法:

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();

TimeoutProcessKiller超时进程杀手

public class TimeoutProcessKiller extends TimerTask {
    private Process p;

    public TimeoutProcessKiller(Process p) {
        this.p = p;
    }

    public void run() {
        p.destroy();
    }
}

Thank you for any advise.谢谢你的任何建议。

Your problem is most likely because your batch script has kicked off sub-processes which are still running after your task has destroyed the parent.您的问题很可能是因为您的批处理脚本已经启动了子进程,这些子进程在您的任务破坏了父进程后仍在运行。 Change the TimeoutProcessKiller.run() method to print off the descendants (child process and all their children) and then kill them as well.更改TimeoutProcessKiller.run()方法以打印出descendants (子进程及其所有子进程),然后也将其杀死。

The following will print the PID of each one as it tries to kill them:以下将打印每个尝试杀死它们的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);
}

The change you made from Runtime.exec() to ProcessBuilder is not the cause - as Runtime.exec() is a call to ProcessBuilder .您从Runtime.exec()ProcessBuilder所做的更改不是原因 - 因为Runtime.exec()是对ProcessBuilder的调用。 The issue with descendants goes away if you don't consume the STDOUT stream ( NOT a sensible thing to ignore as this can freeze the process), so you most likely added the BufferedReader lineReader... after swapping from Runtime.exec() ?如果您不使用 STDOUT stream ,后代的问题就会消失(这不是一件明智的事情,因为这会冻结进程),所以您很可能在从Runtime.exec()交换之后添加了BufferedReader lineReader...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM