2017-01-05 13 views
0

タイムアウト値を設定しているときにプロセスの出力を取得するにはどうすればよいですか?Javaプロセスが出力を取得してタイムアウトを設定する

私は現在、プロセスの標準出力とエラー出力から文字列を作成するために、apache commons io utilsを使用しています。

以下のコードは(コメントとともに)終了するプロセスで正常に動作します。ただし、プロセスが終了しない場合、メインスレッドは終了しません!

コメント付きコードのコメントを外してprocess.waitfor()をコメントアウトすると、メソッドは非終了プロセスを適切に破棄します。しかし、プロセスを終了するためには、出力が正しく取得されません。 waitfor()が完了すると、プロセスの入力ストリームとエラーストリームを取得できないようです。

最後に、process.waitfor()が現在のところにコメントされたセクションを移動しようとすると、process.waitfor()を削除してコメントのセクションのコメントを外し、終了していないプロセスの場合はメインスレッドも停止しません。これは、process.waitfor(15、...)に決して到達しないためです。 @EJPが示唆したように

private static Outputs runProcess(String command) throws Exception { 
    Process process = Runtime.getRuntime().exec(command); 

    // if (!process.waitFor(15, TimeUnit.SECONDS)) { 
    // System.out.println("Destroy"); 
    // process.destroy(); 
    // } 

    // Run and collect the results from the standard output and error output 
    String stdStr = IOUtils.toString(process.getInputStream()); 
    String errStr = IOUtils.toString(process.getErrorStream()); 

    process.waitFor(); 

    return new Outputs(stdStr, errStr); 
} 
+0

を処理するさまざまな方法を説明して非常に良いブログです。 – EJP

答えて

1

は、あなたはストリームをキャプチャしたりProcessBuilderを使用するか、コマンドからファイルにリダイレクトする別のスレッドを使用することができます。
ここでは、私があなたが使用できる3つのアプローチがあります。

  1. ストリームには異なるスレッドを使用します。ファイルへの出力&エラーをリダイレクトして、ファイルから読み込むためにあなたのコマンドでリダイレクト演算子を使用しProcessBuilder

    ProcessBuilder processBuilder = new ProcessBuilder("cat") 
         .redirectError(new File("error")) 
         .redirectOutput(new File("output")); 
    
    Process process = processBuilder.start(); 
    
    // process.waitFor(); 
    if (!process.waitFor(3, TimeUnit.SECONDS)) { 
        System.out.println("Destroy"); 
        process.destroy(); 
    } 
    
    System.out.println(FileUtils.readFileToString(new File("output"))); 
    System.out.println(FileUtils.readFileToString(new File("error"))); 
    
  2. を使用して

    Process process = Runtime.getRuntime().exec("cat "); 
    
    ExecutorService newFixedThreadPool = Executors.newFixedThreadPool(2); 
    
    Future<String> output = newFixedThreadPool.submit(() -> { 
        return IOUtils.toString(process.getInputStream()); 
    }); 
    Future<String> error = newFixedThreadPool.submit(() -> { 
        return IOUtils.toString(process.getErrorStream()); 
    }); 
    
    newFixedThreadPool.shutdown(); 
    
    // process.waitFor(); 
    if (!process.waitFor(3, TimeUnit.SECONDS)) { 
        System.out.println("Destroy"); 
        process.destroy(); 
    } 
    
    System.out.println(output.get()); 
    System.out.println(error.get()); 
    

Hereあなたが別のスレッドで出力を取得する必要がありRuntime.Exec

関連する問題