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:

Anónimo dijo...

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

Felipe Martínez D. dijo...

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!

Julius dijo...

Oh muy bueno el tuto felicidades y gracias!

Felipe Martínez D. dijo...

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

gorrotxa dijo...

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.

Felipe Martínez D. dijo...

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.

Charly Zer dijo...

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

Felipe Martínez D. dijo...

Hola Charly, gracias a tí por comentar.

nada dijo...

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?

nada dijo...

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.

Felipe Martínez D. dijo...

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.

Anónimo dijo...

oye amigo pero no me acepta el comando sudo en linux

Felipe Martínez D. dijo...

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.

Seba dijo...

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

Felipe Martínez D. dijo...

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.

EDUARDO BARRAGÁN dijo...

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

Felipe Martínez D. dijo...

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.

Pablo López dijo...

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

Felipe Martínez D. dijo...

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.

Anónimo dijo...

Gracias por el aporte!!

Unknown dijo...

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

Felipe Martínez D. dijo...

Hola David.

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

Saludos.

marvic dijo...

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

Felipe Martínez D. dijo...

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.

matias dijo...

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?

Felipe Martínez D. dijo...

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.

Anónimo dijo...

Si quisiera ejecutar dos comandos seguidos como sería?

Felipe Martínez D. dijo...

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.

Anónimo dijo...

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

Felipe Martínez D. dijo...

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

Saludos.

diego dijo...

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?

Felipe Martínez D. dijo...

Hola Diego.

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

Saludos.

Unknown dijo...

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 ?

Felipe Martínez D. dijo...

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.

Unknown dijo...

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

Felipe Martínez D. dijo...

Hola Karen.

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

Saludos cordiales.

Anónimo dijo...

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

Felipe Martínez D. dijo...

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.

Anónimo dijo...

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

Unknown dijo...

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

Alberto dijo...

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.

Felipe Martínez D. dijo...

@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.

Alberto dijo...

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

Felipe Martínez D. dijo...

Me alegro de que lo hayas solucionado.

Un saludo.

Anónimo dijo...

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

Felipe Martínez D. dijo...

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.

Publicar un comentario

Felinfo: Java, Linux, Virtualización. Open Source.  ©Template Blogger Green by Dicas Blogger .

TOPO