2010-01-18 7 views
6

Estoy llamando a programas de línea de comandos conectados por pipes. Todo esto funciona en Linux con seguridad.Java exec() no devuelve el resultado esperado de los comandos conectados de pipes

Mi método:

protected String execCommand(String command) throws IOException { 
    String line = null; 
    if (command.length() > 0) { 
     Process child = Runtime.getRuntime().exec(command); 
     InputStream lsOut = child.getInputStream(); 
     InputStreamReader r = new InputStreamReader(lsOut); 
     BufferedReader in = new BufferedReader(r); 

     String readline = null; 
     while ((readline = in.readLine()) != null) { 
      line = line + readline; 
     } 
    } 

    return line; 
} 

Si estoy llamando a algún archivo gato | grep asd, estoy obteniendo el resultado esperado. Pero no todos los comandos funcionan correctamente. Por ejemplo con esto:

cat /proc/cpuinfo | wc -l 

o esto:

cat /proc/cpuinfo | grep "model name" | head -n 1 | awk -F":" '{print substr($2, 2, length($2))} 

el método devolverá nulo. Supongo que este problema depende de los comandos de formato de salida como cabeza, cola, wc, etc. ¿Cómo puedo evitar este problema y obtener el resultado final de la salida?

+1

Inútil (utiliza * 3) del 'cat'. –

+0

@Dennis - de hecho. ¡Bien descrito! –

+0

@Bobby Lo he intentado, esto no ayuda. – Pawka

Respuesta

2

Todavía no se encontró la solución adecuada para ejecutar los comandos canalizados con Runtime.exec, pero se encontró una solución. Simplemente escribí estos guiones para separar los archivos bash. Entonces Runtime.exec llama a estos scripts bash y obtiene el resultado esperado.

+0

Esta es la única solución que encontré a través de google. No puedes aceptar tu propia respuesta? De todos modos, muchas gracias. –

+0

Parece que puedo :-) – Pawka

8

La tubería (como la redirección, o >) es una función del shell, por lo que la ejecución directamente desde Java no funcionará. Es necesario hacer algo como:

/bin/sh -c "your | piped | commands | here" 

que ejecuta un proceso de shell con la línea de comandos (incluyendo tuberías) especificada después del -c (entre comillas).

Nótese también que usted tiene que consumir stdout y stderr al mismo tiempo, de lo contrario su proceso generado bloqueará la espera de su proceso de consumir la salida (o errores). Más información here.

+0

Thx para la respuesta pero esto todavía no resuelve el problema. – Pawka

2

Todo el que use Runtime.exec debería leer this.

0

Lo rápido y sucio a hacer sería:

command = "/bin/sh -c '" + command.replaceAll("'", "'\''") + "'" 

Normalmente, tendrá que estar atento a la inyección de comandos (es decir, alguien se cuela "; rm -rf /;" en el comando). Pero eso es solo un problema si parte del comando puede ser suministrado desde alguna otra entrada del usuario.

El enfoque lento y doloroso sería hacer la tubería Bash usted mismo en Java. Si continúa por este camino, encontrará todos los wonderful things that Bash gives you que no están disponibles directamente en Process.exec (tuberías, redirección, comandos compuestos, expansión variable, evaluación aritmética, ...).

  1. Analice el comando para | caracteres. Asegúrese de tener cuidado con || y las cadenas entre comillas.
  2. Engendre un nuevo Process por cada comando de canalización.
  3. Crea Thread s que leen la salida de un comando y lo escriben en la entrada del siguiente comando.
0

Probablemente un poco demasiado tarde, pero para otros que buscan una solución, intente esto ...

String[] cmd = { 
         "/bin/sh", 
         "-c", 
         "cat /proc/cpuinfo | wc -l" 
        }; 

Process process = Runtime.getRuntime().exec(cmd); 

Todo lo mejor ..

Cuestiones relacionadas