Vuoi il trucco?
Non avviare il processo da ProcessBuilder.start() . Non cercare di interferire con il reindirizzamento/consumo di stream da Java (soprattutto se non te ne frega niente; )
Usa ProcessBuilder.start() per avviare un piccolo script di shell che fagocita tutti i flussi di input/output.
Qualcosa del genere:
#!/bin/bash
nohup $1 >/dev/null 2>error.log &
Cioè:se non ti interessa stdout e vuoi comunque registrare stderr (vero?) in un file (error.log qui).
Se non ti interessa nemmeno stderr, reindirizzalo a stdout:
#!/bin/bash
nohup $1 >/dev/null 2>1 &
E chiami quel minuscolo script da Java, dandogli come argomento il nome del processo che vuoi eseguire.
Se un processo in esecuzione su Linux che reindirizza sia stdout che stderr a /dev/null continua a produrre qualsiasi cosa allora hai un'installazione di Linux non funzionante e non conforme;)
In altre parole:quanto sopra Just Works [TM] e sbarazzarsi del problematico "devi consumare i flussi in questo e quell'ordine bla bla bla non-senso specifico di Java" .
Se il processo scrive in stderr
o stdout
, e non lo stai leggendo - semplicemente "si bloccherà", bloccando quando scrivi su stdout/err
. Reindirizza stdout/err
a /dev/null
usando una shell o unendo stdout/err
con redirectErrorStream(true) e genera un altro thread che legge da stdout
del processo
Il thread che esegue il processo potrebbe bloccarsi se non gestisce l'output. Questo può essere fatto generando un nuovo thread che legge l'output del processo.
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();