martes, 15 de diciembre de 2009

Ejecutar comandos Linux y MS-Dos desde Java













Poder controlar nuestro sistema desde el código de programación puede resultar muy útil en muchos casos. Así como el hecho de conseguir información, por ejemplo, de la configuración de nuestra red para usarlo en nuestras aplicaciones. Ése es el caso que nos ocupa ahora: queremos obtener nuestra dirección IP y configuración de red desde Java. Además, aprovechando la portabilidad de este lenguaje, haremos que la aplicación funcione tanto en Linux, como en Windows.

 

El código


import java.io.*;

public class EjecutarComando {

        public static void main(String args[]) {

                String s = null;

                try {

                        // Determinar en qué SO estamos
                        String so = System.getProperty("os.name");

                        String comando;

                        // Comando para Linux
                        if (so.equals("Linux"))
                                comando = "ifconfig";

                        // Comando para Windows
                        else
                                comando = "cmd /c ipconfig";

                        // Ejcutamos el comando
                        Process p = Runtime.getRuntime().exec(comando);

                        BufferedReader stdInput = new BufferedReader(new InputStreamReader(
                                        p.getInputStream()));

                        BufferedReader stdError = new BufferedReader(new InputStreamReader(
                                        p.getErrorStream()));

                        // Leemos la salida del comando
                        System.out.println("Ésta es la salida standard del comando:\n");
                        while ((s = stdInput.readLine()) != null) {
                                System.out.println(s);
                        }

                        // Leemos los errores si los hubiera
                        System.out
                                        .println("Ésta es la salida standard de error del comando (si la hay):\n");
                        while ((s = stdError.readLine()) != null) {
                                System.out.println(s);
                        }

                        System.exit(0);
                } catch (IOException e) {
                        System.out.println("Excepción: ");
                        e.printStackTrace();
                        System.exit(-1);
                }
        }
}

46 comentarios:

  1. donde puedo encontrar un manual que me explique paso a paso cada linea mil gracias mi correo es diegoarnulfocatano@gmail.com

    ResponderEliminar
  2. Gracias a tí por comentar.

    Para saber lo que hace cada parte del código, puedes guiarte por los comentarios. Los comentarios son las líneas que enpiezan por //.

    Si te estás iniciando en Java, un buen manual es el "Aprenda Java como si estuviera en Primero". Lo puedes encontrar aquí:

    http://www.it.uniovi.es/docencia/Telematica/appTel/material/AprendaJava.pdf

    Espero haberte ayudado.

    Saludos!

    ResponderEliminar
  3. Oh muy bueno el tuto felicidades y gracias!

    ResponderEliminar
  4. Gracias Julius, me alegra que te haya sido útil.

    ResponderEliminar
  5. que bueno, tenia prisa por probar el java, por los editores tipo netbeans y la maravilla de la multiplataforma y resulta que puedo ejecutar mis bash scripts en el entorno java, se agradece. Ya tendré tiempo de mirarme el manual, tiene buena pinta.

    ResponderEliminar
  6. Así es Gorrotxa.

    El poder ejecutar comandos y scripts de linux desde java abre un gran abanico para desarrollar aplicaciones. También en windows desde ms-dos, pero por si no se ha notado, me va más el SO del pinguino.

    Saludos.

    ResponderEliminar
  7. que buena onda compartir conocimientos! chido post! y gracias me fue de utilidad ;)

    ResponderEliminar
  8. Hola, me ha servido este tuto muchas gracias, solo una pregunta, si el comando que quiero ejecutar necesita permisos de root, por ejemplo "sudo nautilus", ¿como podría hacer para que el usuario de permiso?

    ResponderEliminar
  9. ahhh lo acabo de encontrar: seria "gksudo nautilus" en el caso de gnome y "kdesudo nautilus" en el caso de kde, y automáticamente se levanta una ventana para ingresar la contraseña.

    ResponderEliminar
  10. Hola Hugotuxsv.

    Buena pregunta, no me la había planteado. Efectivamente con gksudo y kdesudo se resuelve el problema. Tengo que estudiar si se podría introducir la contraseña desde la aplicación Java, lo expondré si doy con la forma.

    Me alegro de que te sirviera.

    Saludos.

    ResponderEliminar
  11. oye amigo pero no me acepta el comando sudo en linux

    ResponderEliminar
  12. Hola.

    Tal y como indican en el comentario anterior, tienes que utilizar gksudo (si estás en gnome) en lugar de sudo. Cuando ejecutes el comando te saltará una ventana en la que deberás introducir la contraseña de administrador.

    Si utilizas kde, debes utilizar kdesudo en lugar de sudo.

    Saludos.

    ResponderEliminar
  13. Hola

    Estoy tratando de ejecutar el comando convert para crear pdfs desde una aplicación en Java, el punto es que no funciona cuando parte del nombre o ruta de uno de los archivos a usar contiene un espacio. Sabes cómo podría arreglarlo?

    Saludos

    ResponderEliminar
  14. Hola Seba.

    Intenta referenciar ese archivo de esta forma: poniendo File/// y sustituye los espacios en blanco por %20 . Ejemplo:

    file:///C:/Pdfs/Curso%20de%20Java.pdf

    Coméntame si te funciona.

    Saludos.

    ResponderEliminar
  15. Muy buen tutorial amigo, como le hago para seguir ingresando mas comandos algo asi como una pequeña termina.

    Es decir mantener abierta la sesion de root

    ResponderEliminar
  16. Hola EDD.

    No sabría responderte a lo que me preguntas, ya que este ejemplo es muy sencillo y no permite un "diálogo" con el terminal, osea, que te pida la contraseña después de introducir un comando que la requiera. La solución gksudo serviría solo para comandos que hagan una llamada a aplicaciones visuales, como "sudo gksudo nautilus".

    La solución más aproximada que se ocurre es mediante "sudo gkasudo -s", introducir la contraseña y a continuación los comandos que quieres ejecutar con permisos de administrador. Se supone que con la opción -s ya no te pediría más la contraseña para los siguientes comandos que quieras ejecutar.

    Pruébalo si quieres y me comentas qué tal te fue.

    Saludos y gracias por comentar.

    ResponderEliminar
  17. Hola, buscando como ejecutar comandos linux desde java me encontré con este post, y me ha servido de ayuda. Sin embargo, no consigo ejecutar el comando que yo quiero. Probando este sistema con comandos como "ls -la" funciona, incluso si pongo "gedit" se me abre el editor. Pero lo que yo quiero, que es ejecutar el "gcc" para compilar unos ficheros .c, no funciona! Alguna sugerencia? Este es el codigo que utilizo.

    String [] command = {"gcc", "-g", path+"/*.c" ,"-o", path+"/ejecutable"};
    final Process proc = Runtime.getRuntime().exec(command);

    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);
    }
    //...y sacamos el resultado por pantalla
    System.out.println(ret.toString());

    Muchas gracias por la colaboracion ;)

    ResponderEliminar
  18. Hola Pablo.

    Dado que el comando que quieres ejecutar es relativamente complejo, yo te aconsejaría que creases un script que contenga el comando y desde la aplicación Java simplemente llames a dicho script.

    Por ejemplo, el script se puede llamar compilacion.sh y estará guardado en tu directorio personal. Desde el código Java lo llamarías así:

    // Ejcutamos el comando
    Process p = Runtime.getRuntime().exec("sh ~/compilacion.sh");


    Si esta solución no es exactamente lo que estabas buscando o encuentras algún problema, coméntamelo.

    Saludos y Feliz Navidad.

    ResponderEliminar
  19. Gracias por el aporte!!

    ResponderEliminar
  20. hola sé que es muy tarde para comentar aquí pero quisiera hacerte una pregunta:

    me mandaron un deber donde en java y a través del cmd debo ejecutar una aplicación .jar pero al ubicarla no sé ejecuta,lo que yo hago es:

    comando = "cmd /c Java -jar LZW.jar";

    donde LZW es mi aplicación....
    que debo hacer
    y de antemano muchas gracias...

    ResponderEliminar
  21. Hola David.

    La forma de hacerlo que indicas es correcta. ¿Qué inconvenientes encuentras? ¿Te aparece algún error?.

    Saludos.

    ResponderEliminar
  22. Hola

    Me ha servido de mucha ayuda, te agradeceria si me pudieras ayudar. La linea qeu yo ejecuto es un compilador (llvm) y querria saber como hago para detectar si ha creado un fichero (ya que generaria .o) y la salida del compilador me sale como error, por lo que no se como deberia de comprobar si genero el fichero que necesito.

    Muchisimas gracias, tarde mucho en econtrar algo tan claro como esto

    ResponderEliminar
  23. Hola marvic.

    ¿El error que te aparece te lo da también cuando lo ejecutas directamente en el terminal linux? ¿Qué error te da?. Para comprobar si te ha generado el fichero .o puedes crearte un script y lanzarlo desde java. El script sería así:

    if [ -f archivo.o ] then
    echo archivo.o existe
    fi

    Espero que te sea de ayuda.

    Saludos.

    ResponderEliminar
  24. Hola tengo un problema al ejecutar este comando no me copia el archivo en windows7: comando = "cmd /c xcopy file:///C:/xampp/mysql/data/regcivildb file:///D:/bakup_SIREC"
    cual puede ser el problema?

    ResponderEliminar
  25. Hola Matías.

    ¿Has intentado ejecutar el comando directamente en el terminal de MS-DOS? ¿Te copia correctamente el archivo o te da algún error?. Asegúrate de que el archivo existe y el directorio de destino también.

    Saludos.

    ResponderEliminar
  26. Si quisiera ejecutar dos comandos seguidos como sería?

    ResponderEliminar
  27. Mi recomendación sería que creases un método así:

    private String ejecutarComando(String comando){
    ...
    }

    En los puntos suspensivos podría el código de este artículo desde:

    Process p = Runtime.getRuntime().exec(comando);

    hasta el final. Y que como parámetro de salida devolvieses los errores (en vez de hacer "System.out.println(s);", poner "return s;"

    Una vez que tuvieses ese método, podrías llamarlo todas las veces que quisieses:

    String mensaje = ejecutarComando(comando1);
    mensaje = ejecutarComando(comando2);
    ...


    Si tienes dudas, dímelo e intentaré ayudarte.

    Saludos.

    ResponderEliminar
  28. gracias felipe me quedo mucho mejor porque lo que hacia era comando = dir && ipconfig && .....

    ResponderEliminar
  29. De nada. Si tienes alguna duda más, coméntamelo.

    Saludos.

    ResponderEliminar
  30. amigo necesito un código que me ayude a saber el valor de unas resistencia utilizando los colores sera que me puede ayudar conseguir el código?

    ResponderEliminar
  31. Hola Diego.

    Aquí preguntan lo mismo: http://es.answers.yahoo.com/question/index?qid=20101128142510AAQcnZS

    Saludos.

    ResponderEliminar
  32. Hola he seguido los consejos del tutorial,lo que quiero hacer es ejecutar el siguiente comando de linux para imprimir un archivo seleccionando la impresora y la ruta del archivo pero no me logra funcionar el comando es el siguiente:
    lp -d HP_LaserJet_Profesional_P1102w /home/pi/doc.pdf
    Podrías aconsejarme ?

    ResponderEliminar
  33. Hola Javier.

    ¿Qué mensaje te aparece cuando lo ejecutas desde tu aplicación?. ¿Has comprobado que el comando se ejecuta correctamente desde el terminal Linux?.

    Saludos.

    ResponderEliminar
  34. Hola me gustaria saber como quedaria el codigo si quisiera mostrarlo por ventanas emegerntes con JOPtionPane.ShowInputMessage y JOPtionPane.ShowInputDialog

    ResponderEliminar
  35. Hola Karen.

    Indícame que problemas tienes para aplicar JOPtionPane.ShowInputMessage y JOPtionPane.ShowInputDialog e intentaré ayudarte.

    Saludos cordiales.

    ResponderEliminar
  36. hola se que es un pocooooooooo tarde para comentar pero es que aunque me sirve muy bien el código para algunos comandos para el que necesito ejecutar me da problemas, si pudieran ayudarme
    los comados que necesito ejecutar son
    gksudo hdparm -I /dev/sda
    gksudo smartctl -a /dev/sda

    y el error que me da es este

    Ésta es la salida standard del comando:

    smartctl 6.3 2014-07-26 r3976 [i686-linux-3.2.0-4-686-pae] (local build)
    Copyright (C) 2002-14, Bruce Allen, Christian Franke, www.smartmontools.org

    ATA device successfully opened

    Use 'smartctl -a' (or '-x') to print SMART (and more) information

    Ésta es la salida standard de error del comando (si la hay):

    en el primer caso me muestar la ayuda de gksudo como si no llegara a ver el hdparm y me dice gksudo: opción inválida -- I

    y en el segundo caso

    ResponderEliminar
  37. Hola.

    Prueba a ejecutar esos comandos desde el terminal a ver si te dan el mismo error. Indica qué es lo que quieres hacer con esos comandos.

    Saludos.

    ResponderEliminar
  38. muchas gracias por responder felipe, ya logré resolver mi problema aquí te dejo la solución de cómo lo hice:

    String[ ] comando = {"/bin/bash", "-c", "echo ...contraseña... |sudo -S hdparm -i /dev/sda"};

    ahora tengo el mismo problema pero para el lenguaje C, ya encontré la función system(comado) pero me fuinciona solo para algunos comandos no para todos y en especial da problemas para los que necesitan permiso de ejecución como los que comenté la primera vez, cualquier ayuda sera agradecida.
    Saludos

    ResponderEliminar
  39. Una pregunta como puedo hacer para ejecutar un ping y un ipconfig desde netbeans para un sistema operativo Windows?? Gracias

    ResponderEliminar
  40. Hola a quién corresponda ;-) Yo tengo una duda. Quiero compilar muchos archivos java (*.java) a través del Runtime.getRuntime().exec. Si lo hago desde línea de comandos ningún problema y me crea los .class pero si lo hago desde desde código java y pongo la instrucción no me hace nada. PATH, CLASSPATH, JAVA_HOME, todo está bien configurado pero sigue sin crearme los.class y no me da ningún error eh. ¿Alguna idea de alguien que le haya pasado? Saludos y gracias.

    ResponderEliminar
  41. @Anónimo Me alegro de que encontraras la solución. Sobre el lenguaje C no te puedo ayudar, ya que hace tiempo que no lo utilizo.

    @Maick Bonro ¿has intentado ejecutar ping e ipconfig desde Netbeans? ¿Qué mensaje o error te aparece?. No tengo Netbeans instalado y no te puedo ayudar, pero entiendo que funcionará igualmente que en Eclipse, que es el IDE que utilicé yo.

    @Alberto Cuando ejecutas tu código java, ¿te da alguna excepción?. Si utilizas mi ejemplo debería de aparecerte un mensaje "Excepción: ..." . Eso nos dará algunas pistas de lo que está pasando.

    Saludos a todos.

    ResponderEliminar
  42. Gracias Felipe por contestar tan rápido. Ya lo he solucionado. El problema era que no utilizaba correctamente el comando javac. Un saludo

    ResponderEliminar
  43. Me alegro de que lo hayas solucionado.

    Un saludo.

    ResponderEliminar
  44. A alguien le ocurre que se cierra el programa después de ejecutar el programa en java?

    ResponderEliminar
  45. Hola.

    A mí no me ocurre. Si ejecutas el código que te indico aquí, podrás depurar la causa de tu error, ya que lo capturo el error con try/catch . Indícame qué error te da e intentaré ayudarte.

    Saludos.

    ResponderEliminar