So führen Sie einen Shell-Befehl in Java aus

So führen Sie einen Shell-Befehl in Java aus

1. Überblick

In diesem Tutorial werden die beiden Möglichkeiten vonexecuting a shell command from within Java code veranschaulicht.

Die erste besteht darin, die KlasseRuntimezu verwenden und die Methodeexecaufzurufen.

Die zweite und anpassbarere Möglichkeit besteht darin, eineProcessBuilder-Instanz zu erstellen und zu verwenden.

2. Betriebssystemabhängigkeit

Bevor wir ein neuesProcesserstellen, das unseren Shell-Befehl ausführt, müssen wir zuerst das Betriebssystem ermitteln, auf dem unserJVMausgeführt wird.

Dies liegt daran, dass wir aufWindows unseren Befehl als Argument für die Shell voncmd.exeausführen müssen und auf allen anderen Betriebssystemen eine Standard-Shell namenssh: ausgeben können

boolean isWindows = System.getProperty("os.name")
  .toLowerCase().startsWith("windows");

3. Ein- und Ausgang

Darüber hinaus benötigen wir eine Möglichkeit, sich in die Eingabe- und Ausgabeströme unseres Prozesses einzuklinken.

Mindestensthe output must be consumed - Andernfalls wird unser Prozess nicht erfolgreich zurückgegeben, sondern bleibt hängen.

Implementieren wir eine häufig verwendete Klasse namensStreamGobbler, dieInputStream verbraucht:

private static class StreamGobbler implements Runnable {
    private InputStream inputStream;
    private Consumer consumer;

    public StreamGobbler(InputStream inputStream, Consumer consumer) {
        this.inputStream = inputStream;
        this.consumer = consumer;
    }

    @Override
    public void run() {
        new BufferedReader(new InputStreamReader(inputStream)).lines()
          .forEach(consumer);
    }
}

NOTE: Diese Klasse implementiert dieRunnable-Schnittstelle, was bedeutet, dass sie von jedemExecutor ausgeführt werden kann.

4. Runtime.exec()

Ein Methodenaufruf anRuntime.exec() ist eine einfache, noch nicht anpassbare Möglichkeit, einen neuen Unterprozess zu erzeugen.

Im folgenden Beispiel fordern wir eine Verzeichnisliste des Home-Verzeichnisses eines Benutzers an und drucken es auf der Konsole aus:

String homeDirectory = System.getProperty("user.home");
Process process;
if (isWindows) {
    process = Runtime.getRuntime()
      .exec(String.format("cmd.exe /c dir %s", homeDirectory));
} else {
    process = Runtime.getRuntime()
      .exec(String.format("sh -c ls %s", homeDirectory));
}
StreamGobbler streamGobbler =
  new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

5. ProcessBuilder

Für die zweite Implementierung unseres Computerproblems verwenden wirProcessBuilder. Dies wird dem Ansatz vonRuntimevorgezogen, da wir einige Details anpassen können.

Zum Beispiel können wir:

  • Ändern Sie das Arbeitsverzeichnis, in dem unser Shell-Befehl ausgeführt wird, mitbuilder.directory()

  • Richten Sie mitbuilder.environment() eine benutzerdefinierte Schlüsselwertzuordnung als Umgebung ein

  • Leiten Sie Eingabe- und Ausgabestreams zu benutzerdefinierten Ersetzungen um

  • erben beide mitbuilder.inheritIO() an die Streams des aktuellenJVM-Prozesses

ProcessBuilder builder = new ProcessBuilder();
if (isWindows) {
    builder.command("cmd.exe", "/c", "dir");
} else {
    builder.command("sh", "-c", "ls");
}
builder.directory(new File(System.getProperty("user.home")));
Process process = builder.start();
StreamGobbler streamGobbler =
  new StreamGobbler(process.getInputStream(), System.out::println);
Executors.newSingleThreadExecutor().submit(streamGobbler);
int exitCode = process.waitFor();
assert exitCode == 0;

6. Fazit

Wie wir in diesem kurzen Tutorial gesehen haben, können wir einen Shell-Befehl inJava auf zwei verschiedene Arten ausführen.

Wenn Sie die Ausführung des erzeugten Prozesses anpassen möchten, um beispielsweise sein Arbeitsverzeichnis zu ändern, sollten Sie im Allgemeinen die Verwendung vonProcessBuilder in Betracht ziehen.

Wie immer finden Sie die Quellenon GitHub.