Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
usuario590444
fuente
fuente
Respuestas:
Hay muchas razones por las que
waitFor()
no vuelve.Pero generalmente se reduce al hecho de que el comando ejecutado no se cierra.
Esto, nuevamente, puede tener muchas razones.
Una razón común es que el proceso produce algunos resultados y no lee las secuencias adecuadas. Esto significa que el proceso se bloquea tan pronto como el búfer esté lleno y espera a que su proceso continúe leyendo. Su proceso, a su vez, espera a que termine el otro proceso (que no lo hará porque espera su proceso, ...). Ésta es una situación clásica de estancamiento.
Debe leer continuamente el flujo de entrada de los procesos para asegurarse de que no se bloquee.
Hay un buen artículo que explica todas las trampas
Runtime.exec()
y muestra formas de evitarlas llamado "Cuando Runtime.exec () no lo hará" (sí, el artículo es de 2000, ¡pero el contenido aún se aplica!)fuente
waitFor()
no regresa.Parece que no está leyendo el resultado antes de esperar a que termine. Esto está bien solo si la salida no llena el búfer. Si lo hace, esperará hasta que lea el resultado, catch-22.
Quizás tenga algunos errores que no está leyendo. Esto haría que la aplicación se detenga y espere a que espere eternamente. Una forma sencilla de evitar esto es redirigir los errores a la salida normal.
fuente
pb.redirectError(new File("/dev/null"));
redirectError
solo está disponible desde Java 1.7También de Java doc:
Prueba esto:
fuente
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
donde stoutOS y stderrOS sonBufferedOutputStream
los que he creado para escribir en los archivos apropiados.process.close()
. Pero cuando abro el flujo de entrada como se sugirió anteriormente y lo cierro inmediatamente, el problema desaparece. Entonces, en mi caso, Spring estaba esperando la señal de cierre de flujo. Aunque estoy usando Java 8 que se puede cerrar automáticamente.Me gustaría agregar algo a las respuestas anteriores, pero como no tengo el representante para comentar, solo agregaré una respuesta. Esto está dirigido a usuarios de Android que están programando en Java.
Según la publicación de RollingBoy, este código casi funcionó para mí:
En mi caso, waitFor () no se estaba publicando porque estaba ejecutando una declaración sin retorno ("ip adddr flush eth0"). Una forma sencilla de solucionar este problema es simplemente asegurarse de que siempre devuelve algo en su estado de cuenta. Para mí, eso significó ejecutar lo siguiente: "ip adddr flush eth0 && echo done". Puede leer el búfer todo el día, pero si no se devuelve nada, su hilo nunca liberará su espera.
¡Espero que ayude a alguien!
fuente
process.waitFor()
que se cuelga, es elreader.readLine()
que se cuelga si no tienes salida. Intenté usar elwaitFor(long,TimeUnit)
tiempo de espera hasta si algo sale mal y descubrí que era la lectura el colgado. Lo que hace que la versión temporizada requiera otro hilo para hacer la lectura ...Hay varias posibilidades:
stdout
.stderr
.stdin
.fuente
Como han mencionado otros, debes consumir stderr y stdout .
En comparación con las otras respuestas, desde Java 1.7 es aún más fácil. Ya no tiene que crear subprocesos usted mismo para leer stderr y stdout .
Simplemente use los
ProcessBuilder
métodos y useredirectOutput
en combinación conredirectError
oredirectErrorStream
.fuente
Por la misma razón, también puede usar
inheritIO()
para mapear la consola Java con la consola de la aplicación externa como:fuente
Debería intentar consumir salida y error al mismo tiempo
fuente
Creo que observé un problema similar: algunos procesos se iniciaron, parecían ejecutarse correctamente pero nunca se completaron. La función waitFor () estaba esperando para siempre, excepto si maté el proceso en el Administrador de tareas.
Sin embargo, todo funcionó bien en los casos en que la longitud de la línea de comando fuera de 127 caracteres o menos. Si los nombres de archivo largos son inevitables, es posible que desee utilizar variables ambientales, lo que puede permitirle mantener corta la cadena de línea de comandos. Puede generar un archivo por lotes (usando FileWriter) en el que establece sus variables ambientales antes de llamar al programa que realmente desea ejecutar. El contenido de dicho lote podría verse así:
El último paso es ejecutar este archivo por lotes utilizando Runtime.
fuente
Aquí hay un método que me funciona. NOTA: Hay algún código dentro de este método que puede no aplicarse a usted, así que intente ignorarlo. Por ejemplo, "logStandardOut (...), git-bash, etc".
}
fuente
La lectura asincrónica de la secuencia combinada con evitar la espera con un tiempo de espera resolverá el problema.
Puede encontrar una página que explica esto aquí http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
fuente