Chcete to trik?
Nezačínejte proces z ProcessBuilder.start() . Nesnažte se zahrávat si s přesměrováním/spotřebou streamu z Javy (zejména pokud se na to nevykašlete; )
Použijte ProcessBuilder.start() ke spuštění malého skriptu shellu, který pohltí všechny vstupní/výstupní proudy.
Něco takového:
#!/bin/bash
nohup $1 >/dev/null 2>error.log &
To znamená:pokud vás stdout nezajímá a přesto chcete protokol stderr (vy?) do souboru (error.log zde).
Pokud vás ani stderr nezajímá, přesměrujte ho na stdout:
#!/bin/bash
nohup $1 >/dev/null 2>1 &
A zavoláte tomu malému skriptu z Javy a jako argument mu uvedete název procesu, který chcete spustit.
Pokud proces běžící na Linuxu, který přesměrovává stdout i stderr na /dev/null, stále produkuje cokoli pak máte rozbitou, nevyhovující instalaci Linuxu;)
Jinými slovy:výše uvedené prostě funguje [TM] a zbavte se problematického „musíte spotřebovávat streamy v tom a tom pořadí bla bla bla nesmysly specifické pro Javu“ .
Pokud proces zapíše do stderr
nebo stdout
, a vy to nečtete - prostě se "zasekne" a zablokuje se při zápisu do stdout/err
. Buď přesměrujte stdout/err
až /dev/null
pomocí shellu nebo sloučení stdout/err
s redirectErrorStream(true) a vytvoří další vlákno, které čte z stdout
procesu
Vlákno, na kterém běží proces, se může zablokovat, pokud nezpracovává výstup. To lze provést vytvořením nového vlákna, které přečte výstup procesu.
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();