/** * NOTE: This copyright does *not* cover user programs that use Hyperic * program services by normal system calls through the application * program interfaces provided as part of the Hyperic Plug-in Development * Kit or the Hyperic Client Development Kit - this is merely considered * normal use of the program, and does *not* fall under the heading of * "derived work". * * Copyright (C) [2010], VMware, Inc. * This file is part of Hyperic. * * Hyperic is free software; you can redistribute it and/or modify * it under the terms version 2 of the GNU General Public License as * published by the Free Software Foundation. This program is distributed * in the hope that it will be useful, but WITHOUT ANY WARRANTY; without * even the implied warranty of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * USA. * */ package org.hyperic.bootstrap; import java.io.ByteArrayOutputStream; import java.io.File; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hyperic.sigar.Sigar; import org.hyperic.sigar.SigarException; import org.hyperic.sigar.SigarFileNotFoundException; import org.hyperic.sigar.ptql.ProcessFinder; import org.hyperic.util.exec.Execute; import org.hyperic.util.exec.ExecuteWatchdog; import org.hyperic.util.exec.PumpStreamHandler; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; /** * Default implementation of {@link ProcessManager} * @author jhickey * */ @Component public class ProcessManagerImpl implements ProcessManager { private Sigar sigar; private final Log log = LogFactory.getLog(ProcessManagerImpl.class); @Autowired public ProcessManagerImpl(Sigar sigar) { this.sigar = sigar; } public long getPidFromPidFile(String pidFile) throws SigarException { return getPidFromProcQuery("Pid.PidFile.eq=" + pidFile); } public long getPidFromProcQuery(String ptql) throws SigarException { long[] pids = ProcessFinder.find(sigar, ptql); if (pids.length > 0) { return pids[0]; } return -1; } public void kill(long pid) throws SigarException { int signum = Sigar.getSigNum("TERM"); sigar.kill(pid, signum); } public void forceKill(long pid) throws SigarException { int signum = Sigar.getSigNum("KILL"); sigar.kill(pid, signum); } public int executeProcess(String[] commandLine, String workingDir, boolean suppressOutput, int timeout) { log.debug("Command line: " +commandLine ); return executeProcess(commandLine, workingDir, null, suppressOutput, timeout); } public int executeProcess(String[] commandLine, String workingDir, String[] envVariables, boolean suppressOutput, int timeout) { ExecuteWatchdog watchdog = null; if (timeout != -1) { watchdog = new ExecuteWatchdog(timeout); } Execute ex = null; if (suppressOutput) { ex = new Execute(new PumpStreamHandler(new ByteArrayOutputStream()), watchdog); } else { // send standard output and error of subprocesses to standard // output and error of the parent process ex = new Execute(new PumpStreamHandler(System.out, System.err), watchdog); } ex.setWorkingDirectory(new File(workingDir)); ex.setCommandline(commandLine); if (envVariables != null) { ex.setEnvironment(envVariables); for (String envVars : envVariables) { log.info("envVariables: " + envVars); } } int exitCode = 0; // log.info("workingDir: " + workingDir); for (String command : commandLine) { log.info("commandLine: " + command); } // try { exitCode = ex.execute(); } catch (Exception e) { exitCode = 1; log.error(e.getMessage(), e); } // Don't log as error if exit code is 143 - will happen if process // is terminated by kill if (exitCode != 0 && exitCode != 143) { String err = "Command did not execute successfully (exit code = " + exitCode + ")"; log.error(err); } else { String info = "Command executed successfully (exit code = " + exitCode + ") "; log.info(info); } if (watchdog != null && watchdog.killedProcess()) { String err = "Command did not complete within timeout of " + timeout + " seconds"; log.error(err); } return exitCode; } public boolean isPortInUse(long port, int maxTries) throws Exception { log.debug("waitForPort " + port + ", entering wait loop: MAXTRIES=" + maxTries); for (int i = 0; i < maxTries; i++) { log.debug("checking port: " + port + "..."); try { if (sigar.getNetListenAddress(port) != null) { // we were able to find something return true; } } catch (SigarFileNotFoundException e) { // means port is not bound } try { Thread.sleep(2000); } catch (InterruptedException e) { // ignore } } log.debug("Num tries for port check exhausted"); return false; } public boolean waitForProcessDeath(int maxTries, long pid) throws Exception { for (int i = 0; i < maxTries; i++) { log.debug("waitForPid: waiting"); pid = getPidFromProcQuery("Pid.Pid.eq=" + pid); if (pid == -1) { log.info("HQ server exited"); return true; } log.debug("waitForPid: PID " + pid + " still alive"); try { Thread.sleep(2000); } catch (InterruptedException e) { // ignore } } log.debug("Num tries for server PID check exhausted"); log.info("HQ server PID " + pid + " did not exit."); return false; } }