2016-06-28 2 views
0

私は外部プロセスでシェルスクリプトを実行しているスレッドを持って実行を停止し、次のように私は、この外部プロセスから標準エラー出力と標準出力ストリームに読み取るためにApacheのIOUtilsを使用しています:スレッドは

Thread t = new Thread(()-> { 
     ProcessBuilder pb = new ProcessBuilder("sh"); 
     Process p = null; 
     try { 
      p = pb.start(); 
      OutputStream os = p.getOutputStream(); 
      os.write("sleep 30 ; echo test".getBytes()); 
      os.flush(); 
      os.close(); 
      InputStream is = p.getInputStream(); 
      InputStream es = p.getErrorStream(); 
      String stdout = IOUtils.toString(is,"UTF-8"); 
      String stderr = IOUtils.toString(es,"UTF-8"); 
      int retval = p.waitFor(); 
     } catch (Exception e) { 
      System.out.println("Got exception: "+e.toString()); 
     } finally { 
      System.out.println("Done now!"); 
     } 
    }); 
t.start(); 
Thread.sleep(7000); 
t.interrupt(); 

何らかの理由で、このテストケースを実行すると、例外がスローされることはありません(catchブロックは実行されません)。finallyブロックは決して実行されません。私が捕まえていない問題がいくつかありますか? stdoutとstderrを別のスレッドで収集する必要がありますか?

答えて

3

stderr用のバッファがいっぱいになると、プログラムが停止します。あなたがそれらを別の文字列にする必要がない限り、私は他の文字列にリダイレクトします。

あなたがバックグラウンドスレッドを起動する必要はありませんので、

waitFor(long, TimeUnit)はタイムアウトを持っている標準エラー出力を読み取るために、追加のスレッドを必要としないので、私は出力を結合するためにProcessBuidler.redirectErrorStreamを使用します。

stderrとstdoutを印刷して、何が間違っているかを示すように表示することをお勧めします。

1

シェルからの出力を処理する前に、スレッドが強制終了(中断)されている点を除いて、正しく表示されます。問題は、シェルが30秒間スリープし、スレッドが7秒で中断されることです。

「シェル」スレッドが実際にアクティブ化される前に、main()メソッドからプログラムを終了すると、catchまたはfinallyブロックからメッセージが表示されないことがあります。