2009-11-13 16 views
16

Vorrei eseguire foo.bat da un programma Groovy e il processo risultante 'output reindirizzato allo stdout. O un esempio di codice Java o Groovy andrebbe bene.Reindirizza l'output del processo allo stdout

foo.bat può richiedere diversi minuti per l'esecuzione e genera molto output, quindi mi piacerebbe vedere l'output non appena viene generato, piuttosto che dover attendere il completamento del processo prima di vedere tutta l'uscita subito.

+0

simile a http://stackoverflow.com/questions/1670798/using-a-thread-to-capture-process-output – yegor256

risposta

29

Questo utilizza una classe che legge tutti gli output generati dal programma eseguito e li visualizza nel proprio stdout.

class StreamGobbler extends Thread { 
    InputStream is; 

    // reads everything from is until empty. 
    StreamGobbler(InputStream is) { 
     this.is = is; 
    } 

    public void run() { 
     try { 
      InputStreamReader isr = new InputStreamReader(is); 
      BufferedReader br = new BufferedReader(isr); 
      String line=null; 
      while ((line = br.readLine()) != null) 
       System.out.println(line);  
     } catch (IOException ioe) { 
      ioe.printStackTrace(); 
     } 
    } 
} 

Runtime rt = Runtime.getRuntime(); 
Process proc = rt.exec("javac"); 
//output both stdout and stderr data from proc to stdout of this process 
StreamGobbler errorGobbler = new StreamGobbler(proc.getErrorStream()); 
StreamGobbler outputGobbler = new StreamGobbler(proc.getInputStream()); 
errorGobbler.start(); 
outputGobbler.start(); 
proc.waitFor(); 
+1

La mia domanda è, che cosa se il processo non è l'output roba in questo momento , il ciclo terminerà prima che il processo finisca, giusto? –

+0

Il ciclo while attenderà fino alla riga successiva di input. – Crummy

4

Ecco qualcosa di un po 'più semplice se si sta solo cercando di afferrare l'output di un comando semplice. Avrai bisogno di usare thread come jitter se vuoi processarli in parallelo o se il tuo comando prende stdin o genera stderr.

Utilizzare una copia bufferizzata (come this) se si sta ottenendo un sacco di output.

import java.io.*; 
public class test { 
    static void copy(InputStream in, OutputStream out) throws IOException { 
    while (true) { 
     int c = in.read(); 
     if (c == -1) break; 
     out.write((char)c); 
    } 
    } 

    public static void main(String[] args) throws IOException, InterruptedException { 
    String cmd = "echo foo"; 
    Process p = Runtime.getRuntime().exec(cmd); 
    copy(p.getInputStream(), System.out); 
    p.waitFor(); 
    } 
} 
4

Il codice Groovy seguente eseguirà foo.bat e inviare l'output a stdout:

println "foo.bat".execute().text 
+4

Penso che questo stamperà solo tutto l'output dopo che il processo è stato completato. Voglio vedere l'output non appena viene generato –

+1

Inoltre, questo fermerà l'esecuzione di foo.bat se l'output di foo.bat è "troppo grande" per il buffer stdout. – billjamesdev

2

modo asincrono per realizzarla.

void inputStreamToOutputStream(final InputStream inputStream, final OutputStream out) { 
    Thread t = new Thread(new Runnable() { 

     public void run() { 
      try { 
       int d; 
       while ((d = inputStream.read()) != -1) { 
        out.write(d); 
       } 
      } catch (IOException ex) { 
       //TODO make a callback on exception. 
      } 
     } 
    }); 
    t.setDaemon(true); 
    t.start(); 
} 

{ 
    Process p = ...; 
    inputStreamToOutputStream(p.getErrorStream(), System.out); 
    inputStreamToOutputStream(p.getInputStream(), System.out); 
} 
6

Se stai cercando di fare questo con Java più Groovy e meno, questo stampa ogni riga come accade:

def cmd = "./longRunningProcess" 

def process = cmd.execute() 
process.in.eachLine { line -> println line } 

In alternativa, se si desidera vedere sia stdout che stderr

def cmd = "./longRunningProcess" 

def process = cmd.execute() 
process.waitForProcessOutput(System.out, System.err) 
35

È semplice reindirizzare tutto lo stream allo standard output utilizzando il metodo inheritIO(). Questo stamperà l'output nello stdout del processo da cui viene eseguito questo comando.

ProcessBuilder pb = new ProcessBuilder("command", "argument"); 
pb.directory(new File(<directory from where you want to run the command>)); 
pb.inheritIO(); 
Process p = pb.start(); 
p.waitFor(); 

Esistono anche altri metodi, come indicato di seguito. Questi singoli metodi aiuteranno a reindirizzare solo il flusso richiesto.

pb.redirectInput(Redirect.INHERIT) 
    pb.redirectOutput(Redirect.INHERIT) 
    pb.redirectError(Redirect.INHERIT) 
+1

Questa è la risposta che risponde correttamente alla domanda. OP ha chiesto come reindirizzare l'output, non come stampare ogni riga dell'output. Differenza molto importante – Brandon

+1

Non riesco a revocarlo abbastanza, mi hai aiutato molto. –

Problemi correlati