¿Cómo agregar un valor de tiempo de espera cuando se utiliza Runtime.exec () de Java?

Tengo un método que estoy usando para ejecutar un comando en el host local. Me gustaría agregar un parámetro de tiempo de espera al método para que, si el comando que se está llamando no finaliza en un tiempo razonable, el método regrese con un código de error. Esto es lo que parece hasta ahora, sin la capacidad de tiempo de espera:

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

¿Alguien puede sugerirme una buena manera de implementar un parámetro de tiempo de espera?

 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; } } } 

Si está utilizando Java 8, simplemente puede usar el nuevo waitFor con tiempo de espera :

 Process p = ... if(!p.waitFor(1, TimeUnit.MINUTES)) { //timeout - kill the process. p.destroy(); // consider using destroyForcibly instead } 

Siguiendo la respuesta de Erickson , creé una forma más genérica de hacer lo mismo.

 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 } } } 

Ahora, todo lo que tienes que hacer es lo siguiente:

 Process process = Runtime.getRuntime().exec(""); ProcessWithTimeout processWithTimeout = new ProcessWithTimeout(process); int exitCode = processWithTimeout.waitForProcess(5000); if (exitCode == Integer.MIN_VALUE) { // Timeout } else { // No timeout ! } 

Implementé esto usando los tres enfoques sugeridos que vienen con el ejemplo de código detallado (soy un novato con la progtwigción de subprocesos y estos códigos de ejemplo fueron invaluables; aún me estaría rascando la cabeza en cuanto a cómo hacer esto si se acaba de explicar en inglés sin código).

Implementé la clase de utilidad que estoy usando para esto con los tres métodos para ejecutar un comando con un tiempo de espera como este:

 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 call = new Callable() { public Integer call() throws Exception { process.waitFor(); return process.exitValue(); } }; // submit the command's call and get the result from a Future 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; } } 

Creé una clase para consumir y mostrar los flujos de salida y error de un comando (tomado de 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(); } } } 

Creé un comando de prueba que tarda aproximadamente 10 segundos en completarse:

 #!/bin/bash sleep 10 echo 'TEST COMMAND RAN OK' 

Luego creé un progtwig de prueba para probar los tres métodos diferentes, llamando a cada uno con un valor de tiempo de espera de 5 segundos (el comando debería fallar) y con un valor de tiempo de espera de 15 segundos (el comando debería tener éxito):

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

Esto es lo que veo cuando ejecuto el progtwig de prueba:

 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 

Entonces, por lo que puedo decir, el enfoque que utiliza una clase de subprocesos Trabajador funciona mejor, ya que da los resultados esperados en ambos casos. El enfoque que usa los ejecutores funciona también como se esperaba, con la advertencia de que parece ejecutar el comando dos veces en el caso de tiempo límite de 15000 ms (es decir, veo la salida para el comando dos veces). El enfoque que utiliza el método sleep () no excede el tiempo de espera del comando en el caso de tiempo de espera de 5000 ms, y muestra el resultado dos veces, pero ejecuta el comando como se esperaba en el caso de tiempo de espera de 15.000 ms.

Para todos los que usan el marco ejecutor: se están olvidando de cerrar el ejecutor. Así que cámbialo a lo siguiente:

 ExecutorService service = Executors.newSingleThreadExecutor(); try { Future ft = service.submit(call); try { int exitVal = ft.get(2000L, TimeUnit.MILLISECONDS); return exitVal; } catch (TimeoutException to) { p.destroy(); throw to; } } finally { service.shutdown(); } 

Si no lo hace, su progtwig mantendrá un hilo activo no daemon, asegurando que su progtwig nunca saldrá hasta que llame a System.exit

Para aquellos que no pueden usar el nuevo método Java 8 waitFor(long timeout, TimeUnit unit) (porque están en Android o simplemente no pueden actualizar), simplemente pueden extraerlo del código fuente JDK y agregarlo en algún lugar de sus utils. archivo :

 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; } 

El único cambio que he hecho en el código fuente original de JDK8 es la adición del parámetro de Process para que podamos llamar al método exitValue del proceso.

El método exitValue intentará devolver o lanzar una IllegalThreadStateException si el proceso aún no ha finalizado. En ese caso, esperamos el tiempo de espera recibido y finalizamos.

El método devuelve un booleano, por lo que si devuelve falso, entonces sabrá que necesita matar el proceso manualmente.

De esta manera parece más simple que cualquier publicación anterior (espere que la llamada directa para esperar).

Una solución liviana para aplicaciones pequeñas:

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

Implementar como un delegado y fallar la llamada si se necesita más de su umbral para completar.

Intente usar un temporizador (o Sleep ()), en un hilo separado o en su cola de eventos si tiene uno disponible.

Hay varias maneras de hacerlo, pero consideraría usar un Executor, solo ayuda a encapsular pasando el valor de salida o la excepción del hilo de regreso al llamador original.

  final Process p = ... Callable call = new Callable() { public Integer call() throws Exception { p.waitFor(); return p.exitValue(); } }; Future ft = Executors.newSingleThreadExecutor().submit(call); try { int exitVal = ft.get(2000L, TimeUnit.MILLISECONDS); return exitVal; } catch (TimeoutException to) { p.destroy(); throw to; } 

Creo que no puedes soslayar la condición de carrera por la que se agota el tiempo de espera, y luego el proceso termina justo antes de llamar a destroy ().

También probé la implementación del trabajador y funciona como un encanto. En el proceso de manejo io, agregué hilos para manejar stde y stdo. Si el hilo de trabajo expira, también salgo de los hilos de 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(); } 

Primero algo de información de antecedentes, me encontré con el problema para tener un tiempo de espera mientras ejecutaba un comando porque el progtwig que intenté ejecutar nunca imprimía ninguna información de errores o errores en caso de error y simplemente seguía reintentando internamente por sí mismo, lo que resultaba en un proceso atascado porque nunca hubo un error o secuencia de salida cuando estaba reintentando.

Entonces, después de process.exec() o process.start() ,

Estaría atrapado para siempre en esta línea,

BufferedReader input = new BufferedReader(newInputStreamReader(process.getInputStream()));

Según 1.8 de Java con public boolean waitFor(long timeout,TimeUnit unit) “idealmente” debería haber public boolean waitFor(long timeout,TimeUnit unit) después del tiempo de espera especificado, pero en mi caso por alguna razón nunca se agotó el tiempo debido a que estaba ejecutando la aplicación como un servicio de Windows (He comprobado los permisos de usuario y todo lo que hay en la cuenta, pero no ayudó).

Así que traté de implementarlo con la siguiente lógica, donde seguiríamos revisando el flujo de entrada con input.ready() y un indicador de tiempo de espera. Esta solución simple funcionaba como un hechizo en comparación con todos los demás que existían.

Código:

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

Puede iniciar un Thread que duerme durante el tiempo que desee y después de la suspensión cambiando un booleano en el que realice un bucle en su método executeCommandLine.

Algo así (no probado ni comstackdo, esta solución es un prototipo, debería refactorizarlo si lo necesita):

 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; } 

y aquí está el 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 puede ayudarte a hacerlo.

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

Si utilizo Java 8 me gustaría ir con Aleksander Blomskøld responder iepwaitFor (1, TimeUnit.MINUTE)

de lo contrario, si Java 6/7 y usando Swing, entonces puede usar un SwingWorker:

  final Process process = ... SwingWorker 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 } 

Sé que esto es realmente un mensaje antiguo; Necesitaba ayuda con un proyecto similar, así que pensé que podría dar algunos de mis códigos que trabajé y otros que funcionan.

 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; 

Espero que esto ayude al futuro: D