2009-06-24 10 views
2

JavaのUnixコマンド(私の場合はps)を定期的に実行する方法はありますか?私が書いたループ:JavaでUnixコマンドを繰り返す

while(this.check) 
{ 
    try 
    { 
      ProcessBuilder pb = new ProcessBuilder("ps"); 
      Process proc; 

      System.out.println(" * * Running `ps` * * "); 

      byte[] buffer; 
      String input; 

      proc = pb.start(); 
      BufferedInputStream osInput = 
       new BufferedInputStream(proc.getInputStream()); 

      //prints 0 every time after the first 
      System.out.println(osInput.available()); 

      buffer = new byte[osInput.available()]; 
      osInput.read(buffer); 
      input = new String(buffer); 
      for(String line : input.split("\n")) 
      { 
       if(line.equals("")) 
        continue; 
       this.handlePS(line); 
      } 

      proc.destroy(); 
      try 
      { 
       Thread.sleep(10000); 
      } 
      catch (InterruptedException ie) 
      { 
       ie.printStackTrace(); 
      } 
     } 
     catch (IOException ioe) 
     { 
      ioe.printStackTrace(); 
     } 
    } 
} 

は動作しません。最初は完全に正常に動作しますが、その後は毎回入力ストリームから0バイトが使用可能です。私はwatchコマンドを試してみましたが、このSolarisのボックスにはありません。 PIDがJavaアプリケーションにあるかどうかを知る必要があるので、私はcronジョブを使用できません。何か案は?

ありがとうございます。

EDIT:それが終了した後、私は同じタイプ(PS)の新しいThreadを作ってるんだ、私は間違いなく新しいProcessBuilderを毎回作っています:

EDIT cronジョブを使用することはできません。

編集:混乱の原因となったので、私はループしませんでした。

+0

私はループが表示されません。 –

+0

混乱を避けるためにループを入れ直してください – geowa4

答えて

3

ループの場所はわかりませんが、ループのたびに新しいProcオブジェクト(したがって、新しいInputStream)を作成する必要があります。それ以外の場合は、最初の呼び出しで常に結果が表示されます。 ProcessBuilderのjavadocsは、毎回それらの1つを作成する必要はないことを示しています。

コールがavailable()のときに入力ストリームがまだ準備されていない競合状態が存在することもあります。結果を出力する前に、入力ストリームがEOFに達していることを確認する必要があります(これはpsで起こりますが、例えばtopとは異なります)。

"ps"の出力がどのようなエンコーディングであるかはわかりませんが(ASCII以外の部分)、エンコーディングは正しく処理されていません。 "ps"はおそらくASCIIであるため、これはかなり安全ですが、他のコマンド(および他の入力ストリーム)では使用できない可能性があります。

+0

ええ、私は毎回新しいプロセスを作っています。コードを読みましたか? – geowa4

+0

混乱を避けるためにループしないでください – geowa4

+0

メソッドの境界が何であるかが明確でないことを考えれば、コードは明確なループ(編集前)を持たない –

1

Kathyの答えに加えて、呼び出しごとにstdoutとstderrを別々のスレッドで収集する必要があります。そうしないと、プロセスはこのデータの読取りを待ってブロックします。

詳細はthis answerを参照してください。

EDIT。終了ステータスを収集するにはwaitFor()に電話していますか?私が通常これにアプローチする方法は、実行してwaitFor()に電話することです。私はこの文脈ではdestroy()が冗長かもしれないと思う。

+0

それを得ました。先端のおかげで!私が実際にプロセスを開始した直後にwaitFor()を呼びました – geowa4

1

だから私は、psの実行が終了する前に入力ストリームをチェックしているというのが問題だと思います。

proc.waitFor()

をosInput.available()を呼び出す前に:追加してみてください。ここで

は、私はそれを実装しているだろうかです:

TimerTask task = new TimerTask() { 

     private void work() throws Exception { 
      System.out.println("Now"); 
      ProcessBuilder pb = new ProcessBuilder("ps"); 
      Process p = pb.start(); 
      p.waitFor(); 
      BufferedReader reader 
       = new BufferedReader(new InputStreamReader(p.getInputStream())); 
      String line; 
      while ((line = reader.readLine()) != null) { 
       // Process line 
       System.out.println(line); 
      } 
     } 

     @Override 
     public void run() { 
      try { 
       work(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    Timer timer = new Timer(); 
    long period = 5000; 
    timer.scheduleAtFixedRate(task, 0, period); 
関連する問題