Java ProcessBuilder: Resultant Process Hangs

You want the trick?

Don't start your process from ProcessBuilder.start(). Don't try to mess with stream redirection/consumption from Java (especially if you give no s**t about it ; )

Use ProcessBuilder.start() to start a little shell script that gobbles all the input/output streams.

Something like that:

#!/bin/bash

nohup $1 >/dev/null 2>error.log &

That is: if you don't care about stdout and still want to log stderr (do you?) to a file (error.log here).

If you don't even care about stderr, just redirect it to stdout:

#!/bin/bash

nohup $1 >/dev/null 2>1 &

And you call that tiny script from Java, giving it as an argument the name of the process you want to run.

If a process running on Linux that is redirecting both stdout and stderr to /dev/null still produce anything then you've got a broken, non-compliant, Linux install ;)

In other word: the above Just Works [TM] and get rid of the problematic "you need to consume the streams in this and that order bla bla bla Java-specific non-sense".


If the process writes to stderr or stdout, and you're not reading it - it will just "hang" , blocking when writing to stdout/err. Either redirect stdout/err to /dev/null using a shell or merge stdout/err with redirectErrorStream(true) and spawn another thread that reads from stdout of the process


The thread running the process may block if it does not handle the output. This can be done by spawning a new thread that reads the output of the process.

    final ProcessBuilder builder = new ProcessBuilder("script")
                    .redirectErrorStream(true)
                    .directory(workDirectory);

    final Process process = builder.start();
    final StringWriter writer = new StringWriter();

    new Thread(new Runnable() {
        public void run() {
            IOUtils.copy(process.getInputStream(), writer);
        }
    }).start();

    final int exitValue = process.waitFor();
    final String processOutput = writer.toString();