Sie wollen das Trick?
Starten Sie Ihren Prozess nicht über ProcessBuilder.start() . Versuchen Sie nicht, sich mit Stream-Umleitung/Verbrauch von Java herumzuärgern (insbesondere, wenn Sie keinen Scheiß darauf geben; )
Verwenden Sie ProcessBuilder.start() um ein kleines Shell-Skript zu starten, das alle Input/Output-Streams verschlingt.
Etwas in der Art:
#!/bin/bash
nohup $1 >/dev/null 2>error.log &
Das heißt:wenn Sie sich nicht um stdout kümmern und trotzdem stderr (oder?) in einer Datei (error.log) protokollieren möchten hier).
Wenn Sie sich nicht einmal für stderr interessieren, leiten Sie es einfach auf stdout um:
#!/bin/bash
nohup $1 >/dev/null 2>1 &
Und Sie rufen dieses winzige Skript von Java aus auf und geben ihm als Argument den Namen des Prozesses, den Sie ausführen möchten.
Wenn ein unter Linux laufender Prozess, der sowohl stdout als auch stderr nach /dev/null umleitet, immer noch alles produziert dann haben Sie eine kaputte, nicht konforme Linux-Installation;)
Mit anderen Worten:Das obige Just Works [TM] und das problematische "Sie müssen die Streams in dieser und jener Reihenfolge verbrauchen, bla bla bla Java-spezifischer Unsinn" loswerden .
Wenn der Prozess in stderr
schreibt oder stdout
, und Sie lesen es nicht - es "hängt" einfach und blockiert beim Schreiben in stdout/err
. Entweder stdout/err
umleiten bis /dev/null
Verwenden Sie eine Shell oder führen Sie stdout/err
zusammen mit RedirectErrorStream(true) und spawnen Sie einen weiteren Thread, der von stdout
liest des Prozesses
Der Thread, der den Prozess ausführt, kann blockieren, wenn er die Ausgabe nicht verarbeitet. Dies kann durch das Spawnen eines neuen Threads erfolgen, der die Ausgabe des Prozesses liest.
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();