Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ProcessBuilder: Forwarding stdout and stderr of started processes without blocking the main thread

I'm building a process in Java using ProcessBuilder as follows:

ProcessBuilder pb = new ProcessBuilder()         .command("somecommand", "arg1", "arg2")         .redirectErrorStream(true); Process p = pb.start();  InputStream stdOut = p.getInputStream(); 

Now my problem is the following: I would like to capture whatever is going through stdout and/or stderr of that process and redirect it to System.out asynchronously. I want the process and its output redirection to run in the background. So far, the only way I've found to do this is to manually spawn a new thread that will continuously read from stdOut and then call the appropriate write() method of System.out.

new Thread(new Runnable(){     public void run(){         byte[] buffer = new byte[8192];         int len = -1;         while((len = stdOut.read(buffer)) > 0){             System.out.write(buffer, 0, len);         }     } }).start(); 

While that approach kind of works, it feels a bit dirty. And on top of that, it gives me one more thread to manage and terminate correctly. Is there any better way to do this?

like image 457
LordOfThePigs Avatar asked Jan 04 '13 21:01

LordOfThePigs


1 Answers

Use ProcessBuilder.inheritIO, it sets the source and destination for subprocess standard I/O to be the same as those of the current Java process.

Process p = new ProcessBuilder().inheritIO().command("command1").start(); 

If Java 7 is not an option

public static void main(String[] args) throws Exception {     Process p = Runtime.getRuntime().exec("cmd /c dir");     inheritIO(p.getInputStream(), System.out);     inheritIO(p.getErrorStream(), System.err);  }  private static void inheritIO(final InputStream src, final PrintStream dest) {     new Thread(new Runnable() {         public void run() {             Scanner sc = new Scanner(src);             while (sc.hasNextLine()) {                 dest.println(sc.nextLine());             }         }     }).start(); } 

Threads will die automatically when subprocess finishes, because src will EOF.

like image 100
Evgeniy Dorofeev Avatar answered Oct 04 '22 20:10

Evgeniy Dorofeev