1概要

このチュートリアルでは、

Java

code内から

シェルコマンドを実行する

2つの方法を説明します。

1つ目は

Runtime

クラスを使用してその

exec

メソッドを呼び出すことです。

よりカスタマイズ可能な2番目の方法は、

ProcessBuilder

インスタンスを作成して使用することです。


2オペレーティングシステムの依存関係

シェルコマンドを実行する新しい

Process

を作成する前に、まず

JVM

が実行されているオペレーティングシステムを確認する必要があります。

これは、

Windows

では、

cmd.exe

シェルの引数としてコマンドを実行する必要があり、他のすべてのオペレーティングシステムでは、__shという標準のシェルを発行できるからです。

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

3.入力と出力

さらに


私たちは私たちのプロセスの入力と出力ストリームにフックする方法が必要です。

少なくとも

出力は消費されなければなりません

– さもなければ私達のプロセスはうまく戻りません、代わりにそれはハングします。


InputStream

を消費する

StreamGobbler

という一般的に使用されるクラスを実装しましょう。

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

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

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

  • 注:** このクラスは

    Runnable

    インタフェースを実装しています。つまり、任意の


    Executor


    によって実行される可能性があります。


4

Runtime.exec()



Runtime.exec()

のメソッド呼び出しは、新しいサブプロセスを生成するための、シンプルでカスタマイズ可能ではない方法です。

次の例では、ユーザーのホームディレクトリのディレクトリ一覧を要求し、それをコンソールに表示します。

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


私たちのコンピューティング問題の2番目の実装では、

ProcessBuilder

を使用します。詳細をカスタマイズできるため、これは

Runtime

アプローチよりも優先されます。

たとえば、

  • シェルコマンドが実行している作業ディレクトリを変更する


builder.directory()

** を使って環境としてカスタムKey-Valueマップを設定する


builder.environment()

** 入力ストリームと出力ストリームをカスタム置換にリダイレクトする

  • 両方を現在の

    JVM

    プロセスのストリームに継承します。


builder.inheritIO()

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. 結論

このクイックチュートリアルで見たように、

Java

でシェルコマンドを実行する方法は2つあります。

一般的に、生成されたプロセスの実行をカスタマイズすることを計画している場合、たとえばその作業ディレクトリを変更する場合は、

ProcessBuilder

を使用することを検討する必要があります。

いつものように、あなたはソース__https://github.com/eugenp/tutorials/tree/master/core-java[on GitHub]を見つけるでしょう。