/** * Build the environment used for all exec calls. * * @return The environment variables. */ public Map<String, String> execEnv(Map<String, String> env) { HashMap<String, String> res = new HashMap<String, String>(); for (String key : appConf.getStrings(AppConfig.EXEC_ENVS_NAME)) { String val = System.getenv(key); if (val != null) { res.put(key, val); } } if (env != null) res.putAll(env); for (Map.Entry<String, String> envs : res.entrySet()) { LOG.info("Env " + envs.getKey() + "=" + envs.getValue()); } return res; }
private ExecServiceImpl() { avail = new Semaphore(appConf.getInt(AppConfig.EXEC_MAX_PROCS_NAME, 16)); }
private ExecBean auxRun(String program, List<String> args, Map<String, String> env) throws NotAuthorizedException, ExecuteException, IOException { DefaultExecutor executor = new DefaultExecutor(); executor.setExitValues(null); // Setup stdout and stderr int nbytes = appConf.getInt(AppConfig.EXEC_MAX_BYTES_NAME, -1); ByteArrayOutputStream outStream = new MaxByteArrayOutputStream(nbytes); ByteArrayOutputStream errStream = new MaxByteArrayOutputStream(nbytes); executor.setStreamHandler(new PumpStreamHandler(outStream, errStream)); // Only run for N milliseconds int timeout = appConf.getInt(AppConfig.EXEC_TIMEOUT_NAME, 0); ExecuteWatchdog watchdog = new ExecuteWatchdog(timeout); executor.setWatchdog(watchdog); CommandLine cmd = makeCommandLine(program, args); LOG.info("Running: " + cmd); ExecBean res = new ExecBean(); if (Shell.WINDOWS) { // The default executor is sometimes causing failure on windows. hcat // command sometimes returns non zero exit status with it. It seems // to hit some race conditions on windows. env = execEnv(env); String[] envVals = new String[env.size()]; int i = 0; for (Entry<String, String> kv : env.entrySet()) { envVals[i++] = kv.getKey() + "=" + kv.getValue(); LOG.info("Setting " + kv.getKey() + "=" + kv.getValue()); } Process proc; synchronized (WindowsProcessLaunchLock) { // To workaround the race condition issue with child processes // inheriting unintended handles during process launch that can // lead to hangs on reading output and error streams, we // serialize process creation. More info available at: // http://support.microsoft.com/kb/315939 proc = Runtime.getRuntime().exec(cmd.toStrings(), envVals); } // consume stderr StreamOutputWriter errorGobbler = new StreamOutputWriter(proc.getErrorStream(), "ERROR", errStream); // consume stdout StreamOutputWriter outputGobbler = new StreamOutputWriter(proc.getInputStream(), "OUTPUT", outStream); // start collecting input streams errorGobbler.start(); outputGobbler.start(); // execute try { res.exitcode = proc.waitFor(); } catch (InterruptedException e) { throw new IOException(e); } // flush errorGobbler.out.flush(); outputGobbler.out.flush(); } else { res.exitcode = executor.execute(cmd, execEnv(env)); } String enc = appConf.get(AppConfig.EXEC_ENCODING_NAME); res.stdout = outStream.toString(enc); res.stderr = errStream.toString(enc); try { watchdog.checkException(); } catch (Exception ex) { LOG.error("Command: " + cmd + " failed. res=" + res, ex); } if (watchdog.killedProcess()) { String msg = " was terminated due to timeout(" + timeout + "ms). See " + AppConfig.EXEC_TIMEOUT_NAME + " property"; LOG.warn("Command: " + cmd + msg + " res=" + res); res.stderr += " Command " + msg; } if (res.exitcode != 0) { LOG.info("Command: " + cmd + " failed. res=" + res); } return res; }