package backtype.storm.command; import backtype.storm.utils.ShellUtils; import backtype.storm.utils.Utils; import com.alibaba.jstorm.client.ConfigExtension; import com.alibaba.jstorm.daemon.supervisor.MachineCheckStatus; import com.alibaba.jstorm.utils.JStormUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Map; /** * @author dongbin.db * @since 2.1.1 */ public class health { private static Logger LOG = LoggerFactory.getLogger(health.class); private static final String NO_RESOURCES = "no_resource"; public static MachineCheckStatus check() { MachineCheckStatus status = new MachineCheckStatus(); Map conf = Utils.readStormConfig(); // firstly check panic's dir status.updatePanic(); runJStormMachineResourceCheckScript(status, conf); if (status.getType() == MachineCheckStatus.StatusType.panic) { return status; } // sencondly check error's dir status.updateError(); runJStormMachineResourceCheckScript(status, conf); if (status.getType() == MachineCheckStatus.StatusType.error) { return status; } // thirdly check waring's dir status.updateWarning(); runJStormMachineResourceCheckScript(status, conf); return status; } private static void runJStormMachineResourceCheckScript(MachineCheckStatus status, Map conf) { try { long timeOut = ConfigExtension.getStormHealthTimeoutMs(conf); List<String> evalScripts = null; if (status.getType().equals(MachineCheckStatus.StatusType.panic)) { evalScripts = getEvalScriptAbsolutePath(ConfigExtension.getStormMachineResourcePanicCheckDir(conf)); } else if (status.getType().equals(MachineCheckStatus.StatusType.error)) { evalScripts = getEvalScriptAbsolutePath(ConfigExtension.getStormMachineResourceErrorCheckDir(conf)); } else if (status.getType().equals(MachineCheckStatus.StatusType.warning)) { evalScripts = getEvalScriptAbsolutePath(ConfigExtension.getStormMachineResourceWarningCheckDir(conf)); } if (evalScripts != null && evalScripts.size() > 0) { for (String command : evalScripts) { ScriptProcessLauncher scriptProcessLauncher = new ScriptProcessLauncher(command, timeOut, status); ExitStatus exit = scriptProcessLauncher.launch(); if (exit.equals(ExitStatus.FAILED)) { return; } } status.updateInfo(); } else { status.updateInfo(); LOG.debug("jstorm machine resource " + status.getType() + "'s check scripts is non-existent"); } } catch (Exception e) { LOG.error("Failed to run machine resource check scripts: " + e.getCause(), e); status.updateInfo(); } } private static List<String> getEvalScriptAbsolutePath(String scriptDir) { if (scriptDir == null) { LOG.debug("jstorm machine resource check script directory is not configured, please check ."); return null; } File parentFile = new File(scriptDir); return getChildLlist(parentFile); } private static List<String> getChildLlist(File parentFile) { List<String> ret = new ArrayList<String>(); if (parentFile.exists()) { File[] list = parentFile.listFiles(); if (list == null) { return ret; } for (File file : list) { if (!file.isDirectory() && file.canExecute()) ret.add(file.getAbsolutePath()); } } LOG.debug("valid scripts are {}", ret); return ret; } static class ScriptProcessLauncher { ShellUtils.ShellCommandExecutor shexec = null; MachineCheckStatus status = null; String execScript; public ScriptProcessLauncher(String execScript, long timeOut, MachineCheckStatus status) { this.status = status; this.execScript = execScript; String[] execString = {execScript}; this.shexec = new ShellUtils.ShellCommandExecutor(execString, null, null, timeOut); } public ExitStatus launch() { ExitStatus exitStatus = ExitStatus.SUCCESS; try { shexec.execute(); } catch (ShellUtils.ExitCodeException e) { exitStatus = ExitStatus.FAILED_WITH_EXIT_CODE; if (shexec.isTimedOut()) { exitStatus = ExitStatus.TIMED_OUT; } LOG.warn(execScript + " exitCode exception, exit code : " + e.getExitCode() + "; the exitStatus is: " + exitStatus); } catch (Exception e) { if (!shexec.isTimedOut()) { exitStatus = ExitStatus.FAILED_WITH_EXCEPTION; } else { exitStatus = ExitStatus.TIMED_OUT; } LOG.warn(execScript + " exception, the exitStatus is: " + exitStatus); LOG.warn(JStormUtils.getErrorInfo(e)); } finally { if (exitStatus == ExitStatus.SUCCESS && notPassed(shexec.getOutput())) { exitStatus = ExitStatus.FAILED; LOG.info("Script execute output: " + shexec.getOutput()); } } return exitStatus; } private boolean notPassed(String output) { String[] splits = output.split("\n"); for (String split : splits) { if (split.startsWith(NO_RESOURCES)) { return true; } } return false; } } private enum ExitStatus { SUCCESS, TIMED_OUT, FAILED_WITH_EXIT_CODE, FAILED_WITH_EXCEPTION, FAILED, NO_RESOURCE } public static void main(String[] args) { health.check(); } }