Quieres el ¿truco?
No inicie su proceso desde ProcessBuilder.start() . No intente meterse con la redirección/consumo de transmisión de Java (especialmente si no le importa nada;)
Utilice ProcessBuilder.start() para iniciar un pequeño script de shell que engulle todos los flujos de entrada/salida.
Algo así:
#!/bin/bash
nohup $1 >/dev/null 2>error.log &
Es decir:si no le importa la salida estándar y aún desea registrar stderr (¿o sí?) en un archivo (error.log aquí).
Si ni siquiera te importa stderr, simplemente redirígelo a stdout:
#!/bin/bash
nohup $1 >/dev/null 2>1 &
Y llamas a ese pequeño script desde Java, dándole como argumento el nombre del proceso que quieres ejecutar.
Si un proceso que se ejecuta en Linux que está redirigiendo tanto stdout como stderr a /dev/null todavía produce cualquier cosa entonces tienes una instalación de Linux rota, no compatible;)
En otras palabras:lo anterior Just Works [TM] y deshacerse del problemático "necesitas consumir las secuencias en este y aquel orden bla bla bla sin sentido específico de Java" .
Si el proceso escribe en stderr
o stdout
, y no lo estás leyendo; simplemente se "colgará", bloqueándose al escribir en stdout/err
. Redireccionar stdout/err
a /dev/null
usando un shell o fusionar stdout/err
con redirectErrorStream(true) y genere otro hilo que lea desde stdout
del proceso
El subproceso que ejecuta el proceso puede bloquearse si no maneja la salida. Esto se puede hacer generando un nuevo hilo que lea el resultado del proceso.
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();