Java 中的进程构建器和进程 - 如何在超时的情况下执行进程:?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5138946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Process Builder and Process in Java - how to execute a process with a timeout :?
提问by mhshams
I need to execute an external batch file in java with a specific timeout. which means that if the batch execution take longer than specified timeout, i need to cancel the execution.
我需要在具有特定超时的 java 中执行外部批处理文件。这意味着如果批处理执行时间超过指定的超时时间,我需要取消执行。
here is a sample code that i wrote:
这是我编写的示例代码:
public static void main(String[] args) throws IOException, InterruptedException {
ProcessBuilder p = new ProcessBuilder("c:\wait.bat", "25"); // batch file execution will take 25 seconds.
final long l = System.currentTimeMillis();
System.out.println("starting..." + (System.currentTimeMillis() - l));
final Process command = p.start();
System.out.println("started..." + (System.currentTimeMillis() - l));
Timer t = new Timer();
t.schedule(new TimerTask() {
@Override
public void run() {
command.destroy();
}
}, 5000); // it will kill the process after 5 seconds (if it's not finished yet).
int i = command.waitFor();
t.cancel();
System.out.println("done..." + (System.currentTimeMillis() - l));
System.out.println("result : " + i);
System.out.println("Really Done..." + (System.currentTimeMillis() - l));
}
the batch file "wait.bat" is something like this:
批处理文件“wait.bat”是这样的:
@echo off
echo starting the process...
@ping 127.0.0.1 -n 2 -w 1000 > nul
@ping 127.0.0.1 -n %1% -w 1000> nul
echo process finished succesfully
@echo on
As you see in the code, batch file will take 25 seconds to finish (first line in main method) and the Timer will destroy the command after 5 seconds.
正如您在代码中看到的,批处理文件需要 25 秒才能完成(main 方法中的第一行),并且 Timer 将在 5 秒后销毁命令。
here is the output of my code:
这是我的代码的输出:
starting...0
started...0
done...5000
result : 1
Really Done...5000
BUILD SUCCESSFUL (total time: 25 seconds)
as you see in output, the last line ("Really Done...") is executed in 5th second but the application is finished after 25 seconds.
正如您在输出中看到的,最后一行(“Really Done...”)在第 5 秒内执行,但应用程序在 25 秒后完成。
my question is that : even though i called the destroy method in my timer, why jvm still waiting for the process to be finished ?
我的问题是:即使我在我的计时器中调用了 destroy 方法,为什么 jvm 仍然在等待进程完成?
回答by Pa?lo Ebermann
It is a bugin Java's Process.destroy()
implementation on Windows. The problem is that the batch-script (or its executing shell) is killed, but does not kill its own child processes (the ping here). Thus, ping is still running after the .destroy()
, and also after the .waitFor()
. But somehow the VM still waits for the ping to finish before finishing itself.
这是Java在 Windows 上的实现中的一个错误Process.destroy()
。问题是批处理脚本(或其正在执行的 shell)被杀死,但不会杀死它自己的子进程(这里的 ping)。因此,ping 仍然在 之后运行.destroy()
,也在.waitFor()
. 但不知何故,VM 在完成之前仍然等待 ping 完成。
It seems there is nothing you can do here from the Java side to really kill the ping reliably.
从 Java 方面来看,您似乎无法在这里真正可靠地终止 ping。
You may think about using start
(in your batch script or outside) to invoke your ping as a separate process.
您可能会考虑使用start
(在您的批处理脚本中或外部)作为一个单独的进程来调用您的 ping。
(See also this previous discussion.)
(另见前面的讨论。)
Or change to a unix-like operation system.
或者换一个类unix的操作系统。
回答by Sergey Grigoriev
If you use Unix/Linux, then write a wrapper bash shell script to interrupt an external command by timeout, then call the wrapper from Java.
如果您使用 Unix/Linux,则编写一个包装器 bash shell 脚本以通过超时中断外部命令,然后从 Java 调用包装器。
The wrapper script looks like
包装脚本看起来像
#!/bin/bash
timeout 60 <your command>
You can detect if timeout expired by checking the script exit code which is 124 in case of timeout
您可以通过检查脚本退出代码(超时时为 124)来检测超时是否已过期
See
看
man timeout
人超时
回答by sdorra
I could be a problem with the cancel method of the timer. try to start the timer as daemon thread.
我可能是计时器的取消方法有问题。尝试将计时器作为守护线程启动。
Timer t = new Timer(true);