Process process = Runtime.getRuntime().exec("tasklist");
BufferedReader reader =
new BufferedReader(new InputStreamReader(process.getInputStream()));
process.waitFor();
java
runtime.exec
user590444
quelle
quelle
Antworten:
Es gibt viele Gründe,
waitFor()
die nicht zurückkehren.Normalerweise läuft es jedoch darauf hinaus, dass der ausgeführte Befehl nicht beendet wird.
Dies kann wiederum viele Gründe haben.
Ein häufiger Grund ist, dass der Prozess eine Ausgabe erzeugt und Sie nicht aus den entsprechenden Streams lesen. Dies bedeutet, dass der Prozess blockiert wird, sobald der Puffer voll ist, und darauf wartet, dass Ihr Prozess weiter liest. Ihr Prozess wartet wiederum darauf, dass der andere Prozess abgeschlossen ist (was nicht der Fall ist, weil er auf Ihren Prozess wartet, ...). Dies ist eine klassische Deadlock-Situation.
Sie müssen kontinuierlich aus dem Eingabestream des Prozesses lesen, um sicherzustellen, dass er nicht blockiert.
Es gibt einen schönen Artikel, der alle Fallstricke erklärt
Runtime.exec()
und Wege um sie herum zeigt: "Wenn Runtime.exec () nicht wird" (ja, der Artikel stammt aus dem Jahr 2000, aber der Inhalt gilt immer noch!)quelle
waitFor()
sie nicht zurückkehrt.Es scheint, dass Sie die Ausgabe nicht lesen, bevor Sie darauf warten, dass sie beendet wird. Dies ist nur dann in Ordnung, wenn die Ausgabe den Puffer nicht füllt. Wenn dies der Fall ist, wird gewartet, bis Sie die Ausgabe catch-22 gelesen haben.
Vielleicht haben Sie einige Fehler, die Sie nicht lesen. Dies würde dazu führen, dass die Anwendung stoppt und wartet, bis sie für immer wartet. Eine einfache Möglichkeit, dies zu umgehen, besteht darin, die Fehler auf die reguläre Ausgabe umzuleiten.
quelle
pb.redirectError(new File("/dev/null"));
redirectError
ist nur seit Java 1.7Auch aus Java doc:
Versuche dies:
quelle
DefaultExecutor executor = new DefaultExecutor(); PumpStreamHandler pumpStreamHandler = new PumpStreamHandler(stdoutOS, stderrOS); executor.setStreamHandler(pumpStreamHandler); executor.execute(cmdLine);
wobei stoutOS und stderrOSBufferedOutputStream
s sind, die ich erstellt habe, um sie in die entsprechenden Dateien zu schreiben.process.close()
. Aber wenn ich den Eingabestream wie oben vorgeschlagen öffne und sofort schließe, verschwindet das Problem. In meinem Fall wartete Spring also auf das Signal zum Schließen des Streams. Obwohl ich Java 8 verwende, kann es automatisch geschlossen werden.Ich möchte den vorherigen Antworten etwas hinzufügen, aber da ich keinen Repräsentanten zum Kommentieren habe, füge ich einfach eine Antwort hinzu. Dies richtet sich an Android-Benutzer, die in Java programmieren.
Laut dem Beitrag von RollingBoy hat dieser Code für mich fast funktioniert:
In meinem Fall wurde waitFor () nicht freigegeben, da ich eine Anweisung ohne Rückgabe ausgeführt habe ("ip adddr flush eth0"). Eine einfache Möglichkeit, dies zu beheben, besteht darin, einfach sicherzustellen, dass Sie immer etwas in Ihrer Erklärung zurückgeben. Für mich bedeutete das, Folgendes auszuführen: "ip adddr flush eth0 && echo done". Sie können den Puffer den ganzen Tag lesen, aber wenn nie etwas zurückgegeben wird, gibt Ihr Thread seine Wartezeit niemals frei.
Hoffe das hilft jemandem!
quelle
process.waitFor()
, was hängt, es ist dasreader.readLine()
, was hängt, wenn Sie keine Ausgabe haben. Ich habe versucht, daswaitFor(long,TimeUnit)
Timeout zu verwenden , wenn etwas schief geht, und festgestellt, dass es das Lesen war, das aufgehängt wurde. Was die Timeout-Version macht, erfordert einen anderen Thread, um das Lesen zu tun ...Es gibt mehrere Möglichkeiten:
stdout
.stderr
.stdin
.quelle
Wie andere bereits erwähnt haben, müssen Sie stderr und stdout konsumieren .
Im Vergleich zu den anderen Antworten ist es seit Java 1.7 noch einfacher. Sie müssen keine Threads mehr selbst erstellen, um stderr und stdout zu lesen .
Verwenden Sie einfach die
ProcessBuilder
und verwenden Sie die MethodenredirectOutput
in Kombination mit entwederredirectError
oderredirectErrorStream
.quelle
Aus dem gleichen Grund können Sie die
inheritIO()
Java-Konsole auch einer externen App-Konsole zuordnen, z.quelle
Sie sollten versuchen, Ausgabe und Fehler gleichzeitig zu verbrauchen
quelle
Ich glaube, ich habe ein ähnliches Problem festgestellt: Einige Prozesse wurden gestartet, schienen erfolgreich zu laufen, wurden jedoch nie abgeschlossen. Die Funktion waitFor () hat ewig gewartet, außer wenn ich den Prozess im Task-Manager abgebrochen habe.
Es funktionierte jedoch alles gut, wenn die Länge der Befehlszeile 127 Zeichen oder weniger betrug. Wenn lange Dateinamen unvermeidlich sind, möchten Sie möglicherweise Umgebungsvariablen verwenden, um die Befehlszeilenzeichenfolge kurz zu halten. Sie können eine Batchdatei (mit FileWriter) generieren, in der Sie Ihre Umgebungsvariablen festlegen, bevor Sie das Programm aufrufen, das Sie tatsächlich ausführen möchten. Der Inhalt einer solchen Charge könnte folgendermaßen aussehen:
Der letzte Schritt ist das Ausführen dieser Batchdatei mit Runtime.
quelle
Hier ist eine Methode, die für mich funktioniert. HINWEIS: Diese Methode enthält Code, der möglicherweise nicht auf Sie zutrifft. Versuchen Sie daher, ihn zu ignorieren. Zum Beispiel "logStandardOut (...), git-bash usw.".
}}
quelle
Das asynchrone Lesen des Streams in Kombination mit dem Vermeiden des Wartens mit einer Zeitüberschreitung löst das Problem.
Eine Seite, die dies erklärt, finden Sie hier http://simplebasics.net/.net/process-waitforexit-with-a-timeout-will-not-be-able-to-collect-the-output-message/
quelle