UPDATE: この記事は、より新しい「ProcessBuilder とプロセスによる Java exec」記事と差し替えました。 このチュートリアルで示した Java コードは単純な「Java exec」ケースで動作しますが、新しい記事では、Java スレッドでシステム コマンドからの出力ストリームを適切に読み取る方法と、必要に応じてコマンドの標準入力に書き込む方法を示しています。

背景やレガシー情報を得るためにこの記事を読むのは自由ですが、新しい「Java exec」記事で共有しているソース コードを使用することを強くお勧めします。 もちろん、Java アプリケーションの移植性が損なわれるため、これについてはあまり読まれていないことでしょう。 例えば、Unixシステム上でJavaアプリケーションを書く場合、「ps -ef」コマンドを実行し、その出力を読むことに興味があるかもしれません。 Unix システムではこれは素晴らしいことですが、残念ながら、Windows システムでは ps コマンドが利用できないため、この同じプログラムは動作しません。

さて、この記事では移植性のことは忘れて、システム コマンドを実行するために使用できる方法を示します。 このトピックについて多くのリクエストをいただきましたので、ご紹介します。

Discussion (Runtime exec and Process)

システム コマンドの実行は比較的簡単です – 一度でも実行したことがあるのなら、それは可能です。 これには、2 つの Java クラス、Runtime クラスと Process クラスの使用が含まれます。 基本的には、Runtimeクラスのexecメソッドを使用して、コマンドを別のプロセスとして実行します。 exec メソッドを呼び出すと、サブプロセスを管理するための Process オブジェクトが返されます。 次に、ProcessオブジェクトのgetInputStream()getErrorStream()メソッドを使って、コマンドの正常な出力と、コマンドのエラー出力を読み取ります。 実行されたコマンドの出力をどうするかは、完全にあなたとあなたが作成するアプリケーション次第です。

(注:プロセスへの書き込みに使用できるgetOutputStream()メソッドもありますが、この記事ではそのメソッドは取り上げません。 これと他のいくつかの高度な機能については、今後の記事で取り上げます。)

A Java exec example

リスト 1 に示すコードでは、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); } }}

リスト 1 というファイル (上記) で私たちの「Java exec」手法の動作例を示しています。

How our Java exec code works

最初に行うことは、Runtime クラスにこのコマンドを供給することによって、実行したいコマンドを指定することです。 Runtimeクラスの独自のインスタンスを作成することはできないので、まずgetRuntimeメソッドを使用して現在のランタイム環境にアクセスし、次にRuntimeのexecメソッドを呼び出す。 これはProcessオブジェクトを返します。

あなたが行う他のすべてのことは、Processオブジェクトのメソッドを含んでいます。 この場合、Unixシステム上で「ps -ef」コマンドを実行しているので、コマンドの出力を読めばいいだけです。 標準エラーの読み取りは、おそらくこのケースでは必要ありませんが、少なくとも、良いプログラミングの実践でないとしても、示す価値があると思いました。

BufferedReader クラスの readLine() メソッドを使用できるように、InputStreamReader と BufferedReader で入力ストリームを変換しています。 これらのクラスを使用するため、このアプリケーションは古い JDK 1.0.x コンパイラーでは正しくコンパイルできません (これらのクラスは 1.0.x では利用できませんでした)。

Download the “Java exec” example source code

このトピックについて長々と述べることができますが、私が推奨できる最善のことは、ソース コードをダウンロードしてしばらくそれを使って作業してみることです。 さまざまなコマンドを実行して、それらが正しく動作するかどうかを確認し、入力を必要とするコマンドを実行してみてください (これは少し複雑になります)。