Muchas veces hay una necesidad de ejecutar un comando Linux (o Windows) desde Java. Las razones pueden ser varias, a veces conviene usar una cosa que ya está disponible en forma de comando (imaginaros el prototipo de un programa con el presupuesto aún sin aprobar) o a lo mejor simplemente porque una utilidad de consola consume mucho menos recursos que Java (supongamos que tenemos que recodificar avi -> fla muchos videos que nos han subido). El caso es que Java sirve perfectamente para ello, teniendo en cuenta ciertas consideraciones.
Veamos el código:
Process proc = Runtime.getRuntime().exec("ls -la");
InputStream is = proc.getInputStream();
int size;
String s;
int exCode = proc.waitFor();
StringBuffer ret = new StringBuffer();
while((size = is.available()) != 0) {
byte[] b = new byte[size];
is.read(b);
s = new String(b);
ret.append(s);
}
System.out.println(ret.toString());
La primera línea nos crea un proceso dentro de nuestro Runtime, con el comando ls -la dentro. Acto seguido obtenemos un InputStream para poder ver la salida estándar del programa. Y aquí viene la primera consideración, en el momento de lanzar el proceso con Runtime.getRuntime().exec() arranca un subproceso que sigue a su ritmo completamente. Quiero decir, si nada más arrancar el proceso intentamos leer lo que ha devuelto tendremos un String vacío, ya que de momento el processo no ha sacado nada por la salida estándar.
La solución para eso es esperar hasta que el proceso termine. Esto lo hacemos con la siguiente línea: proc.waitFor(); Lo que hace es que detiene el Thread dentro del cual hemos lanzado el proceso y espera hasta que termine el proceso (cuidado con los bloqueos). Como resultado devuelve un número entero con el código de terminación del proceso lanzado. Normalmente el código 0 significa OK, en caso de que se haya producido algún error lo normal es que devuelva otro valor.
Las siguientes líneas simplemente leen lo que el proceso ha enviado por la salida estándar y sacan el resultado por pantalla.
Otra consideración de la que no debemos olvidarnos es que un proceso tiene los siguientes flujos (dos de ellos para leer y uno para escribir):
- STDIN – flujo de entrada estándar. Mediante este flujo podemos enviarle datos al comando. Se obtiene mediante Process.getOutputStream().
- STDOUT – flujo de salida estándar. Es el que hemos usado en nuestro ejemplo.
- STDERR – flujo para la salida de errores. Se obtiene mediante Process.getErrorStream().
Segunda parte — como hacer lo mismo pero sin bloquear el Thread.
[...] Ejecutar comandos Linux desde Java (I) [...]
Muchas gracias, me has ayudado mucho, buscaba como esperar al que el proceso terminase (p.waitFor()) y no lo encontraba por ningún lado.
Un saludo.