Java
外部プロセスを実行して、標準出力とエラーの両方を取得できるようにした
kght6123
解説
外部プロセスを実行して、標準出力とエラーの両方を取得できるようにしました。
通常は、非同期で標準出力とエラーを取得する必要があり、毎回、非同期処理を書くのが面倒なため
その処理をInputStreamThread
クラスとProcessTask
を作ることで
どのような、外部プロセスの実行でも使いまわせるようにしました。
ソースコード
private static String execute(final ProcessTask task) {
final StringBuilder output = new StringBuilder();
final ExecutorService pool = Executors.newSingleThreadExecutor();
try
{
final Future<Integer> future = pool.submit(task);
final int exitValue = future.get(60, TimeUnit.SECONDS); // 60秒でタイムアウト
System.out.println("command = " + task.toString() + ";return code = " + exitValue + ".");
//標準出力の内容を出力
for (final String s : task.getInputStream().getStringList()) {
output.append(s).append("\r\n");
}
//標準エラーの内容を出力
for (final String s : task.getErrorStream().getStringList()) {
System.err.println(s);
}
return output.toString();
}
catch (InterruptedException | ExecutionException | TimeoutException e)
{
throw new BuildException(e);
}
finally
{
pool.shutdownNow();
}
}
import java.util.concurrent.Callable;
public class ProcessTask implements Callable<Integer> {
private final String[] commands;
private InputStreamThread inputStream;
private InputStreamThread errorStream;
public ProcessTask(String... commands)
{
super();
this.commands = commands;
}
@Override
public Integer call() throws Exception
{
final ProcessBuilder pb = new ProcessBuilder(commands);
final Process process = pb.start();
try
{
//InputStreamのスレッド開始
this.inputStream = new InputStreamThread(process.getInputStream());
this.errorStream = new InputStreamThread(process.getErrorStream());
this.inputStream.start();
this.errorStream.start();
process.waitFor();
// InputStreamのスレッド終了待ち
this.inputStream.join();
this.errorStream.join();
return process.exitValue();
}
catch (final Exception e)
{
System.out.println(e.getClass() + "\t" + e.getMessage());
process.destroy();
throw e;
}
}
public InputStreamThread getInputStream() {
return inputStream;
}
public InputStreamThread getErrorStream() {
return errorStream;
}
@Override public String toString() {
final StringBuilder sb = new StringBuilder();
for (final String command : commands) {
sb.append(command);
sb.append(",");
}
return sb.toString();
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;
public class InputStreamThread extends Thread {
private BufferedReader br;
private List<String> list = new ArrayList<String>();
/** コンストラクター */
public InputStreamThread(InputStream is) {
br = new BufferedReader(new InputStreamReader(is));
}
/** コンストラクター */
public InputStreamThread(InputStream is, String charset) {
try {
br = new BufferedReader(new InputStreamReader(is, charset));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
@Override
public void run() {
try {
for (;;) {
String line = br.readLine();
if (line == null) break;
list.add(line);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/** 文字列取得 */
public List<String> getStringList() {
return list;
}
}