varios usados mas getruntime ejemplo ejecutar desde consola comandos comando clase java runtime.exec

usados - runtime java ejemplo



¿Por qué Runtime.exec(String) funciona para algunos pero no para todos los comandos? (1)

¿Por qué fallan algunos comandos?

Esto sucede porque el comando pasado a Runtime.exec(String) no se ejecuta en un shell. El shell realiza muchos servicios de soporte comunes para programas, y cuando el shell no está disponible para realizarlos, el comando fallará.

¿Cuándo fallan los comandos?

Un comando fallará siempre que dependa de las características de un shell. El shell hace muchas cosas comunes y útiles en las que normalmente no pensamos:

  1. El caparazón se divide correctamente entre comillas y espacios.

    Esto asegura que el nombre de archivo en "My File.txt" siga siendo un argumento único.

    Runtime.exec(String) ingenuamente se divide en espacios y pasaría esto como dos nombres de archivo separados. Esto obviamente falla.

  2. El caparazón expande globos / comodines

    Cuando ejecuta ls *.doc , el shell lo reescribe en ls letter.doc notes.doc .

    Runtime.exec(String) no lo hace, solo los pasa como argumentos.

    ls tiene idea de qué es * , por lo que el comando falla.

  3. El shell gestiona tuberías y redirecciones.

    Cuando ejecuta ls mydir > output.txt , el shell abre "output.txt" para la salida del comando y lo elimina de la línea de comando, dando ls mydir .

    Runtime.exec(String) no lo hace. Simplemente los pasa como argumentos.

    ls tiene idea de lo que significa, por lo que el comando falla.

  4. El shell expande variables y comandos

    Cuando ejecuta ls "$HOME" o ls "$(pwd)" , el shell lo reescribe en ls /home/myuser .

    Runtime.exec(String) no lo hace, solo los pasa como argumentos.

    ls tiene idea de lo que significa $ , por lo que el comando falla.

¿Qué puedes hacer en su lugar?

Hay dos formas de ejecutar comandos arbitrariamente complejos:

Simple y descuidado: delegue a un shell.

Simplemente puede usar Runtime.exec(String[]) (tenga en cuenta el parámetro de matriz) y pasar su comando directamente a un shell que puede hacer todo el trabajo pesado:

// Simple, sloppy fix. May have security and robustness implications String myFile = "some filename.txt"; String myCommand = "cp -R ''" + myFile + "'' $HOME 2> errorlog"; Runtime.getRuntime().exec(new String[] { "bash", "-c", myCommand });

Seguro y robusto: asuma las responsabilidades del shell.

Esta no es una solución que se pueda aplicar mecánicamente, pero requiere una comprensión del modelo de ejecución de Unix, qué hacen los shells y cómo puede hacer lo mismo. Sin embargo, puede obtener una solución sólida, segura y robusta quitando el caparazón de la imagen. Esto es facilitado por ProcessBuilder .

El comando del ejemplo anterior que requiere que alguien maneje 1. comillas, 2. variables y 3. redirecciones, puede escribirse como:

String myFile = "some filename.txt"; ProcessBuilder builder = new ProcessBuilder( "cp", "-R", myFile, // We handle word splitting System.getenv("HOME")); // We handle variables builder.redirectError( // We set up redirections ProcessBuilder.Redirect.to(new File("errorlog"))); builder.start();

Cuando intento ejecutar Runtime.exec(String) , ciertos comandos funcionan, mientras que otros comandos se ejecutan pero fallan o hacen cosas diferentes que en mi terminal. Aquí hay un caso de prueba autónomo que demuestra el efecto:

public class ExecTest { static void exec(String cmd) throws Exception { Process p = Runtime.getRuntime().exec(cmd); int i; while( (i=p.getInputStream().read()) != -1) { System.out.write(i); } while( (i=p.getErrorStream().read()) != -1) { System.err.write(i); } } public static void main(String[] args) throws Exception { System.out.print("Runtime.exec: "); String cmd = new java.util.Scanner(System.in).nextLine(); exec(cmd); } }

El ejemplo funciona muy bien si reemplazo el comando con echo hello world , pero para otros comandos, especialmente aquellos que involucran nombres de archivos con espacios como aquí, obtengo errores a pesar de que el comando se está ejecutando claramente:

myshell$ javac ExecTest.java && java ExecTest Runtime.exec: ls -l ''My File.txt'' ls: cannot access ''My: No such file or directory ls: cannot access File.txt'': No such file or directory

Mientras tanto, copiar y pegar en mi shell:

myshell$ ls -l ''My File.txt'' -rw-r--r-- 1 me me 4 Aug 2 11:44 My File.txt

¿Por qué hay una diferencia? ¿Cuándo funciona y cuándo falla? ¿Cómo hago que funcione para todos los comandos?