GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Java ProcessBuilder:Resultierender Prozess hängt

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();

Linux
  1. So starten Sie den Linux-Befehl im Hintergrund und trennen den Prozess im Terminal

  2. So fangen Sie an, eine Programmiersprache zu lernen

  3. Java auf Ubuntu 20.04 LTS installieren – Schritt für Schritt?

  4. Installieren Sie Java auf einem Debian 9-System – Schritt-für-Schritt-Prozess?

  5. Nicht erkannte VM-Option MaxMetaspaceSize=256m – oxd-server konnte nicht gestartet werden [Lösung]

Starten Sie einen Prozess auf einem anderen Tty?

Prozessstartzeit mit Zeitzone?

Wie starte ich einen Prozess in einer eigenen Prozessgruppe?

Linux-Skript zum Beenden des Java-Prozesses

Beenden Sie einen Java-Prozess (in Linux) anhand des Prozessnamens anstelle der PID

Der postgresql-Dienst kann unter CentOS 7 nicht gestartet werden