UPDATE: Dieser Artikel wurde durch meinen neueren Artikel „Java exec mit ProcessBuilder und Process“ ersetzt. Während der in diesem Tutorial gezeigte Java-Code für einfache „Java exec“-Fälle funktioniert, zeigt der neue Artikel, wie man die Ausgabeströme des Systembefehls in Java-Threads richtig liest, und auch, wie man in die Standardeingabe des Befehls schreibt, falls nötig.

Fühlen Sie sich frei, diesen Artikel für Hintergrund-/Legacy-Informationen zu lesen, aber ich empfehle Ihnen dringend, den Quellcode zu verwenden, den ich in meinem neueren „Java exec“-Artikel zur Verfügung stelle, da er die Probleme mit der Standardeingabe, -ausgabe und -fehlern löst, die ich im untenstehenden Code nicht richtig behandelt habe.

Einführung

Ich habe viel über Java gelesen, aber eines der Dinge, die ich selten besprochen sehe, ist, wie Sie externe Systembefehle ausführen sollten. Natürlich lesen Sie wahrscheinlich nicht viel darüber, weil es die Portabilität von Java-Anwendungen beeinträchtigt. Wenn Sie zum Beispiel eine Java-Anwendung auf einem Unix-System schreiben, könnten Sie daran interessiert sein, den Befehl „ps -ef“ auszuführen und die Ausgabe des Befehls zu lesen. Für Unix-Systeme ist das großartig, aber leider funktioniert das gleiche Programm nicht auf einem Windows-System, weil der Befehl ps unter Windows nicht verfügbar ist.

Nun, für diesen Artikel vergessen wir die Portabilität und demonstrieren eine Methode, die zur Ausführung von Systembefehlen verwendet werden kann. Wir haben viele Anfragen zu diesem Thema erhalten, also los geht’s.

Diskussion (Runtime exec und Process)

Das Ausführen eines Systembefehls ist relativ einfach – wenn man es das erste Mal gesehen hat. Es beinhaltet die Verwendung von zwei Java-Klassen, der Runtime-Klasse und der Process-Klasse. Im Wesentlichen verwenden Sie die exec-Methode der Runtime-Klasse, um den Befehl als separaten Prozess auszuführen. Der Aufruf der exec-Methode gibt ein Process-Objekt zur Verwaltung des Unterprozesses zurück. Dann verwenden Sie die Methoden getInputStream() und getErrorStream() des Objekts Process, um die normale Ausgabe des Befehls und die Fehlerausgabe des Befehls zu lesen. Was Sie mit der Ausgabe des ausgeführten Befehls machen, bleibt Ihnen und der Anwendung, die Sie erstellen, überlassen.

(Hinweis: Es gibt auch eine getOutputStream()-Methode, die Sie verwenden können, um in den Prozess zu schreiben, aber wir werden diese Methode in diesem Artikel nicht behandeln. Wir werden diese und einige andere fortgeschrittene Funktionen in einem späteren Artikel behandeln.)

Ein Java exec-Beispiel

Der in Listing 1 gezeigte Code liefert ein funktionierendes Beispiel für unsere „Java exec“-Technik in einer Datei namens JavaRunCommand.java.

import java.io.*;public class JavaRunCommand { public static void main(String args) { String s = null; try { // run the Unix "ps -ef" command // using the Runtime exec method: Process p = Runtime.getRuntime().exec("ps -ef"); BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream())); BufferedReader stdError = new BufferedReader(new InputStreamReader(p.getErrorStream())); // read the output from the command System.out.println("Here is the standard output of the command:\n"); while ((s = stdInput.readLine()) != null) { System.out.println(s); } // read any errors from the attempted command System.out.println("Here is the standard error of the command (if any):\n"); while ((s = stdError.readLine()) != null) { System.out.println(s); } System.exit(0); } catch (IOException e) { System.out.println("exception happened - here's what I know: "); e.printStackTrace(); System.exit(-1); } }}

Listing 1 (oben): Die Datei JavaRunCommand.java zeigt, wie man einen externen Systembefehl aus einem Java-Programm heraus ausführen kann.

Wie unser „Java exec“-Code funktioniert

Das erste, was Sie tun, ist, den auszuführenden Befehl zu spezifizieren, indem Sie diesen Befehl an die Runtime-Klasse übergeben. Da Sie keine eigene Instanz der Runtime-Klasse erstellen können, verwenden Sie zunächst die Methode getRuntime, um auf die aktuelle Laufzeitumgebung zuzugreifen, und rufen dann die Runtime-Methode exec auf. Diese gibt ein Process-Objekt zurück.

Alles andere, was Sie tun, beinhaltet Methoden des Process-Objekts. In diesem Fall, da wir den Befehl „ps -ef“ auf einem Unix-System ausführen, müssen wir nur die Ausgabe des Befehls lesen. Das Lesen des Standardfehlers ist in diesem Fall wahrscheinlich nicht erforderlich, aber ich dachte mir, dass es zumindest zeigenswert ist, wenn nicht sogar gute Programmierpraxis.

Ich konvertiere die Eingabeströme mit InputStreamReader und BufferedReader, so dass ich die Methode readLine() der Klasse BufferedReader verwenden kann. Da ich diese Klassen verwende, lässt sich diese Anwendung mit einem älteren JDK 1.0.x-Compiler nicht richtig kompilieren (diese Klassen waren in 1.0.x nicht verfügbar).

Laden Sie sich den „Java exec“-Beispielquellcode herunter

Ich könnte noch lange über dieses Thema sprechen, aber das Beste, was ich Ihnen empfehlen kann, ist, dass Sie sich den Quellcode herunterladen und eine Weile damit arbeiten. Versuchen Sie, verschiedene Befehle auszuführen, um zu sehen, ob sie richtig funktionieren, und versuchen Sie, einen Befehl auszuführen, der eine Eingabe erfordert (das wird etwas komplizierter sein).