package codeine.utils.os_process; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.log4j.Logger; import codeine.configuration.PathHelper; import codeine.credentials.CredHelper; import codeine.model.Result; import codeine.utils.ReflectionUtils; import codeine.utils.ThreadUtils; import codeine.utils.os_process.ProcessExecuter.ProcessExecuterBuilder; import com.google.common.base.CharMatcher; import com.google.common.base.Splitter; import com.google.common.collect.Lists; import com.google.common.collect.Sets; public class LinuxProcessCleaner { private static final Logger log = Logger.getLogger(LinuxProcessCleaner.class); private static final int SLEEP_BETWEEN_KILL = 3000; private String user; public LinuxProcessCleaner(Process process, String user) { this.user = user; pid = ReflectionUtils.getFieldValue(process, "pid"); } public void cleanup(){ log.info("cleanup linux pid " + pid + " user " + user); Set<String> pids = kill(false, Sets.<String>newHashSet()); ThreadUtils.sleep(SLEEP_BETWEEN_KILL); kill(true, pids); } private Set<String> kill(boolean force, Set<String> pids) { Set<String> pids1 = getPids(); pids1.addAll(pids); if (pids1.isEmpty()) { log.info("pids is empty " + force); return pids1; } ArrayList<String> cmd1 = Lists.newArrayList("kill"); if (force) { cmd1.add("-9"); } cmd1.addAll(pids1); executeAsUserIfNeeded(cmd1); return pids1; } private Set<String> getPids() { List<String> cmd = Lists.newArrayList("/usr/bin/pstree", "-pAl", pid.toString()); Result result = execute(cmd); return getPidsFromOutput(result.output()); } private String encode(final String value) { return CredHelper.encode(value); } private Result execute(List<String> cmd) { return new ProcessExecuterBuilder(cmd).simpleCleanupOnly(true).build().execute(); } private Result executeAsUserIfNeeded(List<String> cmd) { List<String> cmd1; if (user == null) { cmd1 = cmd; } else { cmd1 = Lists.newArrayList(PathHelper.getReadLogs(), encode(user)); for (String string : cmd) { cmd1.add(encode(string)); } } return new ProcessExecuterBuilder(cmd1).simpleCleanupOnly(true).build().execute(); } private static Pattern PATTERN = Pattern.compile(".*[^}]\\((\\d+)\\).*"); private Integer pid; static Set<String> getPidsFromOutput(String output) { Set<String> $ = Sets.newHashSet(); List<String> list = Splitter.on(CharMatcher.anyOf("\n")).splitToList(output); for (String line : list) { List<String> perProcess = Splitter.on(CharMatcher.anyOf("-")).splitToList(line); for (String p : perProcess) { Matcher matcher = PATTERN.matcher(p); if (matcher.matches()) { $.add(matcher.group(1)); } } } log.info("pids from pstree: " + $); return $; } }