将进程重定向到stdout

我想在Groovy程序中执行foo.bat并将生成的进程’输出重定向到stdout。 Java或Groovy代码示例都可以。

foo.bat可能需要几分钟才能运行并产生大量输出,因此我希望在生成后立即看到输出,而不是必须等到进程完成后才能立即看到所有输出。

这使用一个类来读取已执行程序生成的所有输出并将其显示在它自己的标准输出中。

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

使用inheritIO()方法将所有流重定向到标准输出很简单。 这会将输出打印到运行此命令的进程的stdout。

 ProcessBuilder pb = new ProcessBuilder("command", "argument"); pb.directory(new File()); pb.inheritIO(); Process p = pb.start(); p.waitFor(); 

还存在其他方法,如下所述。 这些单独的方法将有助于仅重定向所需的流。

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

如果您希望使用更多Groovy和更少的java来执行此操作,则会在发生时打印每一行:

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

或者,如果你想看到stdout和stderr

 def cmd = "./longRunningProcess" def process = cmd.execute() process.waitForProcessOutput( System.out, System.err ) 

如果你只是试图获取一个简单命令的输出,这里有点简单。 如果要并行处理或者如果命令采用stdin或生成stderr,则需要使用类似jitter的线程。

如果您获得了大量输出,请使用缓冲副本( 如此 )。

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

以下Groovy代码将执行foo.bat并将输出发送到stdout:

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

实现它的异步方式。

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

来自jcabi-log的 VerboseProcess可以帮助您:

 String output = new VerboseProcess(new ProcessBuilder("foo.bat")).stdout();