package com.alibaba.jstorm.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import com.alibaba.jstorm.cluster.StormConfig; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.alibaba.jstorm.client.ConfigExtension; import backtype.storm.utils.Utils; /** * Launch one process for 3 purpose * 1. make the worker process become daemon process, release Supervisor's pressure * 2. catch the exception and log the error message to worker's log, when fail to launch worker, for example wrong jvm parameter * 3. create the log dir, avoid fail to create worker's gc log when dir doesn't exist * * @author longda * */ public class ProcessLauncher { /** * Due to ProcessLaucher will catch the exception when fail to start worker * ProcessLauncher will use the same log as the worker's log * So ProcessLauncher don't log until child process is over. */ private static final Logger LOG = LoggerFactory.getLogger(ProcessLauncher.class); private static class LogWriter extends Thread { private Logger logger; private BufferedReader in; public LogWriter(InputStream in, Logger logger) { this.in = new BufferedReader(new InputStreamReader(in)); this.logger = logger; } public void run() { Logger logger = this.logger; BufferedReader in = this.in; String line; try { while ((line = in.readLine()) != null) { logger.info(line); } } catch (IOException e) { logger.error("Internal ERROR", e); } finally { try { in.close(); } catch (IOException e) { logger.error("Internal ERROR", e); } } } public void close() throws Exception { this.join(); } } private static class LauncherThread extends Thread { private String[] args; private int ret = 0; public LauncherThread(String[] args) { this.args = args; } public void run() { ProcessBuilder pb = new ProcessBuilder(args); Process p; try { p = pb.start(); } catch (IOException e1) { // TODO Auto-generated catch block, log can't print here ret = -1; System.out.println("Failed to start " + JStormUtils.mk_list(args) + "\n" + e1); return; } try { ret = p.waitFor(); LOG.info(JStormUtils.getOutput(p.getErrorStream())); LOG.info(JStormUtils.getOutput(p.getInputStream())); LOG.info("!!!! Wokrer shutdown quickly !!!!"); } catch (InterruptedException e) { ret = 0; System.out.println("Successfully start process"); } catch (Throwable e) { //ret = -1; LOG.error("Unknow exception" + e.getCause(), e); } finally { System.out.println("Begin to exit:" + ret); //JStormUtils.haltProcess(launcher.getResult()); System.exit(ret); } } public int getResult() { return ret; } } public static int getSleepSeconds() { Map<Object, Object> conf = null; try { conf = Utils.readStormConfig(); } catch (Exception e) { conf = new HashMap<Object, Object>(); } return ConfigExtension.getProcessLauncherSleepSeconds(conf); } public static void main(String[] args) throws Exception{ try { System.out.println("Enviroment:" + System.getenv()); System.out.println("Properties:" + System.getProperties()); int sleepSeconds = getSleepSeconds(); int ret = -1; try { if (System.getenv("REDIRECT") != null && System.getenv("REDIRECT").equals("true")) { ProcessBuilder pb = new ProcessBuilder(args); Process p = pb.start(); LogWriter err = null; LogWriter in = null; try { err = new LogWriter(p.getErrorStream(), LOG); err.start(); in = new LogWriter(p.getInputStream(), LOG); in.start(); ret = p.waitFor(); } finally { if (err != null) err.close(); if (in != null) in.close(); } } else { //when worker is dead, supervisor can kill ProcessLauncher right now //once worker start, worker will kill the processLauncher String workerId = System.getenv("jstorm.workerId"); if (StringUtils.isNotBlank(workerId)) { Map conf = Utils.readStormConfig(); StormConfig.validate_distributed_mode(conf); String pidDir = StormConfig.worker_pids_root(conf, workerId); JStormServerUtils.createPid(pidDir); } LauncherThread launcher = new LauncherThread(args); launcher.start(); Thread.sleep(sleepSeconds * 1000); launcher.interrupt(); ret = launcher.getResult(); } } catch (InterruptedException e) { // TODO Auto-generated catch block } finally { System.out.println("Begin to exit:" + ret); //JStormUtils.haltProcess(launcher.getResult()); JStormUtils.haltProcess(ret); } } catch (Exception e) { LOG.error("find error!!", e); throw e; } } }