Java では、UNIX/C のプログラムを、ある意味では特徴付ける、
fork() , exec() , wait() ... といった、プロセスを生成し、プログラムを実行する
働きをもった一群の関数群を、ほとんど用いません。
なぜなら、Java では、cpuにとって重たい処理であるforkに代わって、軽いThreadが、
言語仕様そのものに組み込まれる形で、全面的に使われるからです。
appletの中では、セキュリティの関係で、自由に他のプログラムを実行することは、
許されません。所が、Javaアプリケーションでは、こうしたことが可能になります。
ただ、この時、他のプログラムは、Thread ではなく、forkで生成されたサブ・プロセス
の中で、実行されることになります。今回は、forkで生成されたサブ・プロセス
からの入出力をどう扱うかという問題を取り扱ってみましょう。
次のプログラムは、引数に与えたプログラムを実行してその出力を表示するものです。 簡単な実行例を示します。
sparc04$ java Exec who <---- who コマンドを実行 pid 5357 status 0 Received sigchild for 5357 exit=0 nakaga-h pts/0 6月 25 19:08 (lxb4) maruyama pts/2 6月 25 20:35 (ews1) sparc04$ java Exec ls -l *.txt <---- ls -l *.txt を実行 pid 5328 status 0 Received sigchild for 5328 exit=0 -rw-r--r-- 1 maruyama sysadmin 16681 6月 24日 23:46 sw4.txt sparc04$ java Exec ypcat hosts | grep cronos <---- ホストcronos の検索 202.11.101.9 cronos
このサンプルの中心部分は、次の行です。
proc = Runtime.getRuntime().exec(cmd);
ただ、この行のことは、ドキュメントを見て考えればわかります。
実際には、このサンプルで一番苦労したのは、次の2点です。
第一。サブ・プロセスとJavaとの同期がうまく取れません。 そのために、available()というメソッドを使っています。Streamに データが無いときには、sleepで、ちょっと待つことにしています。 第二。先の行で生成されたprocessオブジェクトから、getInputStream()を 使って、InputStreamを獲得するのですが、InputStreamのままでは、 サブ・プロセスの終了が感知できません
in = new DataInputStream(proc.getInputStream());
というように、DataInputStreamにすると、なぜかわかりませんが、
この問題は解決します。
****************************
** Exec.java
****************************
1 import java.lang.* ;
2 import java.io.* ;
3
4 class Exec {
5 Process proc = null ;
6 DataInputStream in = null;
7
8 Exec( String arg[] ){
9 try{
10 String cmd[] = new String[3] ;
11 StringBuffer args = new StringBuffer();
12
13 if (arg.length == 0) return ;
14 for (int i = 0; i < arg.length; i++) {
15 args.append(' ').append(arg[i]);
16 }
17 cmd[0] = "/usr/bin/ksh";
18 cmd[1] = "-c";
19 cmd[2] = args.toString();
20
21 proc = Runtime.getRuntime().exec(cmd);
22 in = new DataInputStream(proc.getInputStream());
23
24 } catch ( Exception ex){
25 System.err.println("exec: "+ex);
26 }
27 }
28
29 public static void main(String argv[]){
30 try {
31 Exec d = new Exec(argv);
32 String line = null ;
33
34 int size = 0 ;
35 while( true ){
36 if ( d.in.available() > 0 ){
37 while( (line = d.in.readLine()) != null ){
38 System.out.println(line);
39 }
40 break ;
41 } else {
42 Thread.sleep(200);
43 }
44
45 }
46 } catch ( Exception ex){
47 System.err.println("main:"+ex);
48 }
49 }
50 }