package jp.agentec.sinaburocast.common.proc; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; import jp.agentec.sinaburocast.common.SinaburoConstant.LoggerName; import jp.agentec.sinaburocast.common.exception.ProcessExecException; import jp.agentec.sinaburocast.common.util.PropertyUtil; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.log4j.Level; import org.apache.log4j.Logger; /** * 外部プロセスを実行するクラス<br> * コマンドは、スペースで区切って、文字列配列として<br> * 引数に渡す。 * * 同時実行数の制御はしない。 * * @author tsukada * */ public class ProcessUtil { private static final Logger LOGGER = Logger.getLogger(ProcessUtil.class); private static long NO_TIMEOUT = 0L; private static Log DEFAULT_LOGGER = LogFactory.getLog(LoggerName.PROCESS); /** * * 外部コマンドを実行する。(結果は自動的にログに出力し、リターンコードのみ返す) * * @param command コマンドリスト * @param errLogLevel エラー時のログ出力エラーレベル * @return 実行結果 * * @throws ProcessExecException */ public static int execute(List<String> command, Level errLogLevel) throws ProcessExecException { StringBuffer stdErr = new StringBuffer(); Map<String, String> env = new HashMap<String, String>(); env.put("LANG", "C"); int retVal = execute(command, null, stdErr, env, new DefaultReaderWorker(), DEFAULT_LOGGER, PropertyUtil.getInt("DEFAULT_PROCESS_TIMEOUT")); if (stdErr != null && stdErr.length() > 0) { LOGGER.log(errLogLevel, "stdErr:"+stdErr); } return retVal; } /** * 外部コマンドを実行する。(リターンコードのみ返す) * * @param command * @param timeout * @param loggerName * @return * @throws ProcessExecException */ public static int execute(List<String> command, int timeout, String loggerName) throws ProcessExecException { Map<String, String> env = new HashMap<String, String>(); env.put("LANG", "C"); Log logger = StringUtils.isEmpty(loggerName)? DEFAULT_LOGGER: LogFactory.getLog(loggerName); int retVal = execute(command, null, null, env, new DefaultReaderWorker(), logger, timeout); return retVal; } /** * * 外部コマンドを実行する。(エラー出力をStringBufferにセットする) * @param err * * @param command コマンドリスト * @return 実行結果 * * @throws ProcessExecException */ public static int execute(List<String> command, StringBuffer err, int timeout) throws ProcessExecException { return execute(command, null, err, null, null, DEFAULT_LOGGER, timeout); } /** * * 外部コマンドを実行する。(エラー出力をStringBufferにセットする) * @param err * * @param command コマンドリスト * @return 実行結果 * * @throws ProcessExecException */ public static int execute(List<String> command, StringBuffer std, StringBuffer err, int timeout) throws ProcessExecException { return execute(command, std, err, null, null, DEFAULT_LOGGER, timeout); } /** * * 外部コマンドを実行する。(標準出力・エラー出力をStringで返す) * * @param command コマンドリスト * @return 実行結果 * * @throws ProcessExecException */ public static String execute(List<String> command) throws ProcessExecException { StringBuffer std = new StringBuffer(); execute(command, std, std, null, null, DEFAULT_LOGGER, PropertyUtil.getInt("DEFAULT_PROCESS_TIMEOUT")); return std.toString(); } /** * 外部コマンドを実行する。 * * @param command コマンドリスト * @param stdOut 標準出力 * @return 実行結果 * @throws ProcessExecException */ public static int execute(List<String> command, StringBuffer stdOut) throws ProcessExecException { return execute(command, stdOut, null, null, null, DEFAULT_LOGGER, NO_TIMEOUT); } /** * 外部コマンドを実行する。 * * @param command コマンドリスト * @param stdOut 標準出力 * @param stdErr 標準エラー出力 * @param env 環境変数マップ * @return 実行結果 * @throws ProcessExecException */ @SuppressWarnings("unchecked") public static int execute(List<String> command, StringBuffer stdOut, StringBuffer stdErr, Map env) throws ProcessExecException { return execute(command, stdOut, stdErr, env, null, DEFAULT_LOGGER, NO_TIMEOUT); } /** * 外部コマンドを実行する。 * * @param command コマンドリスト * @param stdOut 標準出力 * @param stdErr 標準エラー出力 * @param env 環境変数マップ * @param millisecond タイムアウト(ミリ秒) * @return 実行結果 * @throws ProcessExecException */ @SuppressWarnings("unchecked") public static int execute(List<String> command, StringBuffer stdOut, StringBuffer stdErr, Map env, long millisecond) throws ProcessExecException { return execute(command, stdOut, stdErr, env, null, DEFAULT_LOGGER, millisecond); } /** * 外部コマンドを実行する。 * * @param command コマンドリスト * @param stdOut 標準出力 * @param stdErr 標準エラー出力 * @param env 環境変数マップ * @param readerWorker 標準出力処理クラス * @param errorLog エラーログ出力有無 * @param millisecond タイムアウト(ミリ秒) * @return 実行結果 * @throws ProcessExecException */ @SuppressWarnings("unchecked") public static int execute(List<String> command, StringBuffer stdOut, StringBuffer stdErr, Map env, ReaderWorker readerWorker, Log logger, long millisecond) throws ProcessExecException { LOGGER.info("execute:" + command); ProcessExecutor processExecutor = new ProcessExecutor(stdOut, stdErr, readerWorker, logger, command, env); processExecutor.start(); try { processExecutor.join(millisecond); } catch (InterruptedException e) { LOGGER.error("Thread sleep interrupted.", e); } if (!processExecutor.isCompleted()) { processExecutor.destroyProcess(); if (processExecutor.getException() != null) { LOGGER.info("Process execution failed. " + command + " stdOut:" + stdOut + "stdErr:" + stdErr); throw new ProcessExecException(processExecutor.getException(), ""); } else { LOGGER.info("Process execution failed due to timeout after " + millisecond + " milliseconds " + command + " stdOut:" + stdOut + "stdErr:" + stdErr); throw new ProcessExecException("Process was terminated due to timeout after " + millisecond + " milliseconds", ""); } } return processExecutor.getRetVal(); } public static void main(String[] args) { StringBuffer stdOut = new StringBuffer(); StringBuffer stdErr = new StringBuffer(); String[] cmdArgs = new String[args.length - 1]; for (int i = 0; i < cmdArgs.length; i++) { cmdArgs[i] = args[i + 1]; } try { execute(Arrays.asList(cmdArgs), stdOut, stdErr, null, null, DEFAULT_LOGGER, NumberUtils.toLong(args[0])); } catch (ProcessExecException e) { e.printStackTrace(); } System.out.println("stdOut:" + stdOut); System.out.println("stdErr:" + stdErr); System.out.println("FINISHED!!!!"); } }