如何使用Java的Runtime.exec()时添加超时值?
我有一个方法用来在本地主机上执行一个命令。 我想为该方法添加一个超时参数,以便如果被调用的命令没有在合理的时间内完成,该方法将返回一个错误代码。 这是迄今为止的样子,没有超时的能力:
public static int executeCommandLine(final String commandLine, final boolean printOutput, final boolean printError) throws IOException, InterruptedException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(commandLine); if (printOutput) { BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream())); System.out.println("Output: " + outputReader.readLine()); } if (printError) { BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); System.out.println("Error: " + errorReader.readLine()); } return process.waitFor(); }
任何人都可以提出一个很好的方法来实现一个超时参数?
public static int executeCommandLine(final String commandLine, final boolean printOutput, final boolean printError, final long timeout) throws IOException, InterruptedException, TimeoutException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(commandLine); /* Set up process I/O. */ ... Worker worker = new Worker(process); worker.start(); try { worker.join(timeout); if (worker.exit != null) return worker.exit; else throw new TimeoutException(); } catch(InterruptedException ex) { worker.interrupt(); Thread.currentThread().interrupt(); throw ex; } finally { process.destroy(); } } private static class Worker extends Thread { private final Process process; private Integer exit; private Worker(Process process) { this.process = process; } public void run() { try { exit = process.waitFor(); } catch (InterruptedException ignore) { return; } } }
如果您使用的是Java 8,那么可以简单地使用带有超时的新的waitFor :
Process p = ... if(!p.waitFor(1, TimeUnit.MINUTES)) { //timeout - kill the process. p.destroy(); // consider using destroyForcibly instead }
在埃里克森的回答之后,我创造了一个更通用的方法来做同样的事情。
public class ProcessWithTimeout extends Thread { private Process m_process; private int m_exitCode = Integer.MIN_VALUE; public ProcessWithTimeout(Process p_process) { m_process = p_process; } public int waitForProcess(int p_timeoutMilliseconds) { this.start(); try { this.join(p_timeoutMilliseconds); } catch (InterruptedException e) { this.interrupt(); } return m_exitCode; } @Override public void run() { try { m_exitCode = m_process.waitFor(); } catch (InterruptedException ignore) { // Do nothing } catch (Exception ex) { // Unexpected exception } } }
现在,你所要做的就是如下:
Process process = Runtime.getRuntime().exec("<your command goes here>"); ProcessWithTimeout processWithTimeout = new ProcessWithTimeout(process); int exitCode = processWithTimeout.waitForProcess(5000); if (exitCode == Integer.MIN_VALUE) { // Timeout } else { // No timeout ! }
我使用了三种方法来实现这一点,其中提供了详细的代码示例(我是一个使用线程编程的新手,这些示例代码是非常宝贵的 – 如果只是用英语解释的话,我仍然会挠头没有代码)。
我实现了我正在使用的实用程序类与三个方法执行一个超时如下所示的命令:
package com.abc.network.lifecycle.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Utility class for performing process related functions such as command line processing. */ public class ProcessUtility { static Log log = LogFactory.getLog(ProcessUtility.class); /** * Thread class to be used as a worker */ private static class Worker extends Thread { private final Process process; private Integer exitValue; Worker(final Process process) { this.process = process; } public Integer getExitValue() { return exitValue; } @Override public void run() { try { exitValue = process.waitFor(); } catch (InterruptedException ignore) { return; } } } /** * Executes a command. * * @param command * @param printOutput * @param printError * @param timeOut * @return * @throws java.io.IOException * @throws java.lang.InterruptedException */ public static int executeCommandWithExecutors(final String command, final boolean printOutput, final boolean printError, final long timeOut) { // validate the system and command line and get a system-appropriate command line String massagedCommand = validateSystemAndMassageCommand(command); try { // create the process which will run the command Runtime runtime = Runtime.getRuntime(); final Process process = runtime.exec(massagedCommand); // consume and display the error and output streams StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", printOutput); StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", printError); outputGobbler.start(); errorGobbler.start(); // create a Callable for the command's Process which can be called by an Executor Callable<Integer> call = new Callable<Integer>() { public Integer call() throws Exception { process.waitFor(); return process.exitValue(); } }; // submit the command's call and get the result from a Future<Integer> futureResultOfCall = Executors.newSingleThreadExecutor().submit(call); try { int exitValue = futureResultOfCall.get(timeOut, TimeUnit.MILLISECONDS); return exitValue; } catch (TimeoutException ex) { String errorMessage = "The command [" + command + "] timed out."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } catch (ExecutionException ex) { String errorMessage = "The command [" + command + "] did not complete due to an execution error."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } } catch (InterruptedException ex) { String errorMessage = "The command [" + command + "] did not complete due to an unexpected interruption."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } catch (IOException ex) { String errorMessage = "The command [" + command + "] did not complete due to an IO error."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } } /** * Executes a command. * * @param command * @param printOutput * @param printError * @param timeOut * @return * @throws java.io.IOException * @throws java.lang.InterruptedException */ public static int executeCommandWithSleep(final String command, final boolean printOutput, final boolean printError, final long timeOut) { // validate the system and command line and get a system-appropriate command line String massagedCommand = validateSystemAndMassageCommand(command); try { // create the process which will run the command Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(massagedCommand); // consume and display the error and output streams StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", printOutput); StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", printError); outputGobbler.start(); errorGobbler.start(); // run a thread which will set a flag once it has slept for the timeout period final boolean[] flags = { true }; new Thread() { @Override public void run() { try { Thread.sleep(timeOut); } catch (InterruptedException ex) { String errorMessage = "Timeout loop thread unexpectedly interrupted."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } flags[0] = false; } }.start(); // execute the command and wait int returnValue = -1; while (flags[0] && (returnValue < 0)) { returnValue = process.waitFor(); } // if the command timed out then log it if (returnValue < 0) { log.warn("The command [" + command + "] did not complete before the timeout period expired (timeout: " + timeOut + " ms)"); } return returnValue; } catch (InterruptedException ex) { String errorMessage = "The command [" + command + "] did not complete due to an unexpected interruption."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } catch (IOException ex) { String errorMessage = "The command [" + command + "] did not complete due to an IO error."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } } /** * Executes a command. * * @param command * @param printOutput * @param printError * @param timeOut * @return * @throws java.io.IOException * @throws java.lang.InterruptedException */ public static int executeCommandWithWorker(final String command, final boolean printOutput, final boolean printError, final long timeOut) { // validate the system and command line and get a system-appropriate command line String massagedCommand = validateSystemAndMassageCommand(command); try { // create the process which will run the command Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(massagedCommand); // consume and display the error and output streams StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OUTPUT", printOutput); StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR", printError); outputGobbler.start(); errorGobbler.start(); // create and start a Worker thread which this thread will join for the timeout period Worker worker = new Worker(process); worker.start(); try { worker.join(timeOut); Integer exitValue = worker.getExitValue(); if (exitValue != null) { // the worker thread completed within the timeout period return exitValue; } // if we get this far then we never got an exit value from the worker thread as a result of a timeout String errorMessage = "The command [" + command + "] timed out."; log.error(errorMessage); throw new RuntimeException(errorMessage); } catch (InterruptedException ex) { worker.interrupt(); Thread.currentThread().interrupt(); throw ex; } } catch (InterruptedException ex) { String errorMessage = "The command [" + command + "] did not complete due to an unexpected interruption."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } catch (IOException ex) { String errorMessage = "The command [" + command + "] did not complete due to an IO error."; log.error(errorMessage, ex); throw new RuntimeException(errorMessage, ex); } } /** * Validates that the system is running a supported OS and returns a system-appropriate command line. * * @param originalCommand * @return */ private static String validateSystemAndMassageCommand(final String originalCommand) { // make sure that we have a command if (originalCommand.isEmpty() || (originalCommand.length() < 1)) { String errorMessage = "Missing or empty command line parameter."; log.error(errorMessage); throw new RuntimeException(errorMessage); } // make sure that we are running on a supported system, and if so set the command line appropriately String massagedCommand; String osName = System.getProperty("os.name"); if (osName.equals("Windows XP")) { massagedCommand = "cmd.exe /C " + originalCommand; } else if (osName.equals("Solaris") || osName.equals("SunOS") || osName.equals("Linux")) { massagedCommand = originalCommand; } else { String errorMessage = "Unable to run on this system which is not Solaris, Linux, or Windows XP (actual OS type: \'" + osName + "\')."; log.error(errorMessage); throw new RuntimeException(errorMessage); } return massagedCommand; } }
我创build了一个类来使用和显示来自命令的输出和错误stream(摘自http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4 ):
package com.abc.network.lifecycle.util; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Utility thread class which consumes and displays stream input. * * Original code taken from http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4 */ class StreamGobbler extends Thread { static private Log log = LogFactory.getLog(StreamGobbler.class); private InputStream inputStream; private String streamType; private boolean displayStreamOutput; /** * Constructor. * * @param inputStream the InputStream to be consumed * @param streamType the stream type (should be OUTPUT or ERROR) * @param displayStreamOutput whether or not to display the output of the stream being consumed */ StreamGobbler(final InputStream inputStream, final String streamType, final boolean displayStreamOutput) { this.inputStream = inputStream; this.streamType = streamType; this.displayStreamOutput = displayStreamOutput; } /** * Consumes the output from the input stream and displays the lines consumed if configured to do so. */ @Override public void run() { try { InputStreamReader inputStreamReader = new InputStreamReader(inputStream); BufferedReader bufferedReader = new BufferedReader(inputStreamReader); String line = null; while ((line = bufferedReader.readLine()) != null) { if (displayStreamOutput) { System.out.println(streamType + ">" + line); } } } catch (IOException ex) { log.error("Failed to successfully consume and display the input stream of type " + streamType + ".", ex); ex.printStackTrace(); } } }
我创build了一个testing命令,大约需要10秒钟完成:
#!/bin/bash sleep 10 echo 'TEST COMMAND RAN OK'
然后我创build了一个testing程序来testing三种不同的方法,每个方法的超时值为5秒(命令应该失败),超时值为15秒(命令应该成功):
package com.abc.network.lifecycle.util; public class ProcessUtilityTester { /** * @param args */ public static void main(final String[] args) { try { String command = args[0]; int exitValue = -1; System.out.println("\n\n5000ms timeout With Executors:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithExecutors(command, true, true, 5000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } System.out.println("\n\n5000ms timeout With Sleep:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithSleep(command, true, true, 5000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } System.out.println("\n\n5000ms timeout With Worker:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithWorker(command, true, true, 5000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } System.out.println("\n\n15000ms timeout With Executors:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithExecutors(command, true, true, 15000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } System.out.println("\n\n15000ms timeout With Sleep:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithSleep(command, true, true, 15000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } System.out.println("\n\n15000ms timeout With Worker:"); try { exitValue = -1; exitValue = ProcessUtility.executeCommandWithWorker(command, true, true, 15000); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println("\nExit value:" + exitValue); } } catch (Exception ex) { ex.printStackTrace(); } finally { System.exit(0); } } }
以下是我在运行testing程序时看到的内容:
5000ms timeout With Executors: May 1, 2009 1:55:19 AM com.abc.network.lifecycle.util.ProcessUtility executeCommandWithExecutors SEVERE: The command [/tmp/testcmd.sh] timed out. java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228) at java.util.concurrent.FutureTask.get(FutureTask.java:91) at com.abc.network.lifecycle.util.ProcessUtility.executeCommandWithExecutors(ProcessUtility.java:179) at com.abc.network.lifecycle.util.ProcessUtilityTester.main(ProcessUtilityTester.java:19) java.lang.RuntimeException: The command [/tmp/testcmd.sh] timed out. at com.abc.network.lifecycle.util.ProcessUtility.executeCommandWithExecutors(ProcessUtility.java:186) at com.abc.network.lifecycle.util.ProcessUtilityTester.main(ProcessUtilityTester.java:19) Caused by: java.util.concurrent.TimeoutException at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:228) at java.util.concurrent.FutureTask.get(FutureTask.java:91) at com.abc.network.lifecycle.util.ProcessUtility.executeCommandWithExecutors(ProcessUtility.java:179) ... 1 more Exit value:-1 5000ms timeout With Sleep: OUTPUT>TEST COMMAND RAN OK OUTPUT>TEST COMMAND RAN OK Exit value:0 5000ms timeout With Worker: May 1, 2009 1:55:34 AM com.abc.network.lifecycle.util.ProcessUtility executeCommandWithWorker SEVERE: The command [/tmp/testcmd.sh] timed out. java.lang.RuntimeException: The command [/tmp/testcmd.sh] timed out. at com.abc.network.lifecycle.util.ProcessUtility.executeCommandWithWorker(ProcessUtility.java:338) at com.abc.network.lifecycle.util.ProcessUtilityTester.main(ProcessUtilityTester.java:47) Exit value:-1 15000ms timeout With Executors: OUTPUT>TEST COMMAND RAN OK OUTPUT>TEST COMMAND RAN OK Exit value:0 15000ms timeout With Sleep: OUTPUT>TEST COMMAND RAN OK Exit value:0 15000ms timeout With Worker: OUTPUT>TEST COMMAND RAN OK Exit value:0
所以从我可以告诉的方法使用一个工作者线程类的作品是最好的,因为它在两种情况下给出了预期的结果。 使用执行程序的方法也按预期工作,但要注意的是,它似乎在15000ms的timout情况下运行了两次命令(即,我看到命令的输出两次)。 使用sleep()方法的方法不会在5000ms超时情况下按预期超时该命令,并显示输出两次,但在15000ms超时情况下按预期运行命令。
对于每个使用执行者框架的人:你们都忘记closures执行者。 所以将其更改为以下内容:
ExecutorService service = Executors.newSingleThreadExecutor(); try { Future<Integer> ft = service.submit(call); try { int exitVal = ft.get(2000L, TimeUnit.MILLISECONDS); return exitVal; } catch (TimeoutException to) { p.destroy(); throw to; } } finally { service.shutdown(); }
如果你没有你的程序会保持一个活动的非守护线程,确保你的程序永远不会退出,直到你调用System.exit
适用于小型应用的轻量级解决scheme:
public class Test { public static void main(String[] args) throws java.io.IOException, InterruptedException { Process process = new ProcessBuilder().command("sleep", "10").start(); int i=0; boolean deadYet = false; do { Thread.sleep(1000); try { process.exitValue(); deadYet = true; } catch (IllegalThreadStateException e) { System.out.println("Not done yet..."); if (++i >= 5) throw new RuntimeException("timeout"); } } while (!deadYet); } }
对于那些不能使用新的Java 8方法waitFor(long timeout, TimeUnit unit)
(因为它们在Android上或者根本无法升级)的用户,可以简单地从JDK源代码中提取它,并将其添加到utils中的某个地方文件:
public boolean waitFor(long timeout, TimeUnit unit, final Process process) throws InterruptedException { long startTime = System.nanoTime(); long rem = unit.toNanos(timeout); do { try { process.exitValue(); return true; } catch(IllegalThreadStateException ex) { if (rem > 0) Thread.sleep( Math.min(TimeUnit.NANOSECONDS.toMillis(rem) + 1, 100)); } rem = unit.toNanos(timeout) - (System.nanoTime() - startTime); } while (rem > 0); return false; }
我从JDK8源代码中唯一修改了原来的一个,是添加了Process
参数,以便我们可以从该过程中调用exitValue
方法。
如果进程尚未终止,则exitValue
方法将直接尝试返回或抛出IllegalThreadStateException
。 在这种情况下,我们等待收到的超时并终止。
该方法返回一个布尔值,所以如果它返回false,那么你知道你需要手动杀死进程。
这种方式似乎比任何上面发布的东西都要简单(期望直接调用waitFor)。
作为一个代表实施,如果超过了你的门槛,完成通话失败。
尝试使用定时器(或睡眠()),在一个单独的线程或如果你有一个可用的事件队列。
有很多种方法可以做到这一点,但我会考虑使用一个Executor–它只是帮助你封装将线程的退出值或exception传回给原来的调用者。
final Process p = ... Callable<Integer> call = new Callable<Integer>() { public Integer call() throws Exception { p.waitFor(); return p.exitValue(); } }; Future<Integer> ft = Executors.newSingleThreadExecutor().submit(call); try { int exitVal = ft.get(2000L, TimeUnit.MILLISECONDS); return exitVal; } catch (TimeoutException to) { p.destroy(); throw to; }
我认为你不能绕过等待时间的竞争条件,然后进程在你调用destroy()之前终止。
我也testing了工人的实施,并像魅力一样工作。 在处理进程io中,我添加了线程来处理stde和stdo。 如果工作线程超时,我也退出io线程。
Process p = Runtime.getRuntime().exec(cmd.trim()); //setup error and output stream threads CommandStreamThread eStream = new CommandStreamThread(p.getErrorStream(), "STDE"); CommandStreamThread oStream = new CommandStreamThread(p.getInputStream(), "STDO"); // kick them off eStream.start(); oStream.start(); //setup a worker thread so we can time it out when we need CommandWorkerThread worker=new CommandWorkerThread(p); worker.start(); try { worker.join(this.getTimeout()); if (worker.getExit() != null) return worker.getExit(); else throw new TimeoutException("Timeout reached:"+this.getTimeout()+" ms"); } catch(InterruptedException ex) { eStream.interrupt(); oStream.interrupt(); worker.interrupt(); Thread.currentThread().interrupt(); throw ex; } finally { p.destroy(); }
首先一些背景信息,我遇到的问题有一个超时,而运行一个命令,因为我试图执行的程序将永远不会打印任何debugging或错误信息的错误,并会继续在本身内部重试导致进程停滞因为在重试时从来没有错误或输出stream。
所以在process.exec()
或process.start()
,
这将永远停留在这条线上,
BufferedReader input = new BufferedReader(newInputStreamReader(process.getInputStream()));
根据java 1.8与public boolean waitFor(long timeout,TimeUnit unit)
方法,它应该有“理想”超时后超时,但在我的情况下,由于某种原因,它永远不会超时可能是因为我运行的应用程序作为一个Windows服务(我已经检查了帐户的用户权限和一切,但没有帮助)。
所以我试着用下面的逻辑来实现它,在这里我们将继续使用input.ready()
和一个超时标志来检查inputstream。这个简单的解决scheme与其他所有的方法相比起到了很大的作用。
码:
public boolean runCommand() throws IOException, InterruptedException, Exception { StringBuilder rawResponse = new StringBuilder(); System.out.println("Running Command " + Arrays.toString(command)); ProcessBuilder processBuilder = new ProcessBuilder(Arrays.asList(command)); processBuilder.redirectErrorStream(true); Process process = processBuilder.start(); //Executing the process BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); waitForTimeout(input, process); //Waiting for Timout String line; while ((line = input.readLine()) != null) { rawResponse.append(line).append("\n"); } return true; } //Timeout method private void waitForTimeout(BufferedReader input, Process process) throws InterruptedException, Exception { int timeout = 5; while (timeout > 0) { if (input.ready()) { break; } else { timeout--; Thread.sleep(1000); if (timeout == 0 && !input.ready()) { destroyProcess(process); throw new Exception("Timeout in executing the command "+Arrays.toString(command)); } } } }
你可以启动一个睡眠的线程,在你想要的时间和睡眠之后改变一个你在executeCommandLine方法中循环的布尔值。
像这样的东西(没有testing,也没有编译,这个解决scheme是一个原型,你应该重构它,如果它适合你的需要):
public static int executeCommandLine(final String commandLine, final boolean printOutput, final boolean printError) throws IOException, InterruptedException { Runtime runtime = Runtime.getRuntime(); Process process = runtime.exec(commandLine); if (printOutput) { BufferedReader outputReader = new BufferedReader(new InputStreamReader(process.getInputStream())); System.out.println("Output: " + outputReader.readLine()); } if (printError) { BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); System.out.println("Error: " + errorReader.readLine()); } ret = -1; final[] b = {true}; new Thread(){ public void run(){ Thread.sleep(2000); //to adapt b[0] = false; } }.start(); while(b[0]) { ret = process.waitFor(); } return ret; }
这里是StreamThread
public class CommandStreamThread extends Thread{ private InputStream iStream; private String cPrompt; CommandStreamThread (InputStream is, String cPrompt) { this.iStream = is; this.cPrompt = cPrompt; } public void run() { try { InputStreamReader streamReader= new InputStreamReader(this.iStream); BufferedReader reader = new BufferedReader(streamReader); String linesep=System.getProperty("line.separator"); String line=null; while ((line=reader.readLine())!=null){ System.out.println(line); //Process the next line seperately in case this is EOF is not preceded by EOL int in; char[] buffer=new char[linesep.length()]; while ( (in = reader.read(buffer)) != -1){ String bufferValue=String.valueOf(buffer, 0, in); System.out.print(bufferValue); if (bufferValue.equalsIgnoreCase(linesep)) break; } } //Or the easy way out with commons utils! //IOUtils.copy(this.iStream, System.out); } catch (Exception e){ e.printStackTrace(); } } public InputStream getIStream() { return iStream; } public void setIStream(InputStream stream) { iStream = stream; } public String getCPrompt() { return cPrompt; } public void setCPrompt(String prompt) { cPrompt = prompt; } }
Apache Commons Exec可以帮助你做到这一点。
请参阅http://commons.apache.org/proper/commons-exec/tutorial.html
String line = "your command line"; CommandLine cmdLine = CommandLine.parse(line); DefaultExecutor executor = new DefaultExecutor(); ExecuteWatchdog watchdog = new ExecuteWatchdog(60000); executor.setWatchdog(watchdog); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); PumpStreamHandler streamHandler = new PumpStreamHandler(outputStream); executor.setStreamHandler(streamHandler); int exitValue = executor.execute(cmdLine); System.out.println(exitValue); System.out.println(outputStream.toString());
如果使用Java 8我会去与AleksanderBlomskøld答案iepwaitFor(1,TimeUnit.MINUTE)
否则,如果Java 6/7和使用Swing,那么你可以使用SwingWorker:
final Process process = ... SwingWorker<Integer, Integer> sw = new SwingWorker<>() { @Override protected Integer doInBackground() throws Exception { process.waitFor(); return process.exitValue(); } }; sw.execute(); int exitValue = sw.get(1, TimeUnit.SECONDS); if (exitValue == 0) { //everything was fine } else { //process exited with issues }
我知道这是真正的旧post; 我需要一些类似项目的帮助,所以我想我可能会给我一些我工作的代码和一些工作的代码。
long current = System.currentTimeMillis(); ProcessBuilder pb = new ProcessBuilder(arguments); try{ pb.redirectErrorStream(true); process = pb.start(); int c ; while((c = process.getInputStream().read()) != -1 ) if(System.currentTimeMillis() - current < timeOutMilli) result += (char)c; else throw new Exception(); return result.trim(); }catch(Exception e){ e.printStackTrace(); } return result;
希望这有助于未来:D