2011-10-13 16 views
5

Me gustaría obtener el resultado de un comando de shell de larga ejecución, ya que está disponible en lugar de esperar a que se complete el comando. Mi código se ejecuta en un nuevo hiloJava Runtime.exec() salida asíncrona

Process proc = Runtime.getRuntime().exec("/opt/bin/longRunning"); 
InputStream in = proc.getInputStream(); 
int c; 
while((c = in.read()) != -1) { 
    MyStaticClass.stringBuilder.append(c); 
} 

El problema con esto es que mi programa en/opt/bin/longRunning tiene que completar antes de que se le asigna InputStream y leer. ¿Hay alguna buena manera de hacer esto de forma asíncrona? Mi objetivo es que una solicitud ajax devuelva el valor actual MyStaticClass.stringBuilder.toString() cada segundo más o menos.

Estoy atascado en Java 5, fyi.

Gracias! W

+0

Gracias a todos! Apache Commons 'Exec es la forma en que fui. @Paul Cager, también brindó una excelente idea. La secuencia de comandos que se llamaba en realidad detectaba que estaba siendo canalizado y bloqueado. Sin embargo, la secuencia que obtiene de Runtime.exec está sincronizada, por lo que si intenta leerla, está bloqueando. – wmarbut

Respuesta

7

Probar con Apache Common Exec. Tiene la capacidad de ejecutar de forma asincrónica un proceso y luego "bombear" la salida a un hilo. Compruebe el Javadoc para obtener más información

1

Runtime.getRuntime(). Exec hace no espera para el comando para terminar, por lo que debería estar recibiendo la salida de inmediato. Tal vez la salida está siendo almacenada temporalmente porque el comando sabe que está escribiendo en una tubería en lugar de en una terminal.

1

Ponga la lectura en un nuevo hilo:

new Thread() { 
    public void run() { 
     InputStream in = proc.getInputStream(); 
     int c; 
     while((c = in.read()) != -1) { 
      MyStaticClass.stringBuilder.append(c); 
     } 
    } 
}.start(); 
+0

Podría estar siendo un poco tonto aquí, pero ¿cómo sacarías tu variable c del hilo? Además, ¿no debería c ser una cadena? –

2

qué escribió el programa que está llamando? Si es así, intente vaciar su salida después de escribir. El texto podría estar atascado en un búfer y no llegar a su programa java.

que utiliza este código para hacer esto y funciona:

Runtime runtime = Runtime.getRuntime(); 
    Process proc = runtime.exec(command); 
    BufferedReader br = new BufferedReader(new InputStreamReader(proc.getInputStream())); 

    while (true) { 

     // enter a loop where we read what the program has to say and wait for it to finish 
     // read all the program has to say 
     while (br.ready()) { 
      String line = br.readLine(); 
      System.out.println("CMD: " + line); 
     } 

     try { 
      int exitCode = proc.exitValue(); 
      System.out.println("exit code: " + exitCode); 
      // if we get here then the process finished executing 
      break; 
     } catch (IllegalThreadStateException ex) { 
      // ignore 
     } 

     // wait 200ms and try again 
     Thread.sleep(200); 

    } 
+0

¿BufferedReader.ready() también cubre el estado de BufferedReader.readLine()? La documentación solo menciona que ready() indica cuándo se puede usar read(), readLine() probablemente será un par de operaciones de lectura(), por lo tanto, este enfoque aún puede bloquearse tal como lo entiendo. – bcause

+0

Tiene razón, se bloqueará y permanecerá en este ciclo hasta que salga el subproceso. Esto es correcto en mi opinión. Si desea hacer algo más antes de que este programa termine de ejecutarse, coloque este código en un hilo separado y haga el otro trabajo en un hilo diferente. No veo una manera de hacer que el InputStream sea devuelto desde el proceso sin bloqueo, como se puede hacer con los sockets de red. En ese caso, arrojaría una excepción de tiempo de espera cuando intente leer de la transmisión. –

0

Proveedores:

try { 
     Process p = Runtime.getRuntime().exec("/opt/bin/longRunning"); 
     BufferedReader in = new BufferedReader( 
            new InputStreamReader(p.getInputStream())); 
     String line = null; 
     while ((line = in.readLine()) != null) { 
     System.out.println(line); } 
Cuestiones relacionadas