in software/base/src/main/java/org/apache/brooklyn/entity/software/base/AbstractSoftwareProcessSshDriver.java [476:619]
protected ScriptHelper newScript(Map<String, ?> flags, String phase) {
if (!Entities.isManagedActive(getEntity()))
throw new IllegalStateException(getEntity()+" is not currently managed here; cannot create script to run here ("+phase+")");
if (!Iterables.all(flags.keySet(), StringPredicates.equalToAny(VALID_FLAGS))) {
throw new IllegalArgumentException("Invalid flags passed: " + flags);
}
ScriptHelper s = new ScriptHelper(this, phase+" "+elvis(entity,this));
if (!groovyTruth(flags.get(NON_STANDARD_LAYOUT))) {
if (groovyTruth(flags.get(DEBUG))) {
s.header.prepend("set -x");
}
if (INSTALLING.equals(phase)) {
// mutexId should be global because otherwise package managers will contend with each other
final String mutexId = "installation lock at host";
s.useMutex(getMutexes(), mutexId, "installing "+elvis(entity,this));
s.header.append(
"export "+INSTALL_DIR_ENV_VAR+"=\""+getInstallDir()+"\"",
"mkdir -p $"+INSTALL_DIR_ENV_VAR,
"cd $"+INSTALL_DIR_ENV_VAR,
"test -f BROOKLYN && exit 0"
);
if (!groovyTruth(flags.get(INSTALL_INCOMPLETE))) {
s.footer.append("date > $INSTALL_DIR/BROOKLYN");
}
// don't set vars during install phase, prevent dependency resolution
s.environmentVariablesReset();
}
if (ImmutableSet.of(CUSTOMIZING, LAUNCHING, CHECK_RUNNING, STOPPING, KILLING, RESTARTING).contains(phase)) {
s.header.append(
"export "+INSTALL_DIR_ENV_VAR+"=\""+getInstallDir()+"\"",
"export "+RUN_DIR_ENV_VAR+"=\""+getRunDir()+"\"",
"mkdir -p $"+RUN_DIR_ENV_VAR,
"cd $"+RUN_DIR_ENV_VAR
);
}
}
if (ImmutableSet.of(LAUNCHING, RESTARTING).contains(phase)) {
s.failIfBodyEmpty();
}
if (ImmutableSet.of(STOPPING, KILLING).contains(phase)) {
// stopping and killing allowed to have empty body if pid file set
if (!groovyTruth(flags.get(USE_PID_FILE)))
s.failIfBodyEmpty();
}
if (ImmutableSet.of(INSTALLING, LAUNCHING).contains(phase)) {
s.updateTaskAndFailOnNonZeroResultCode();
}
if (phase.equalsIgnoreCase(CHECK_RUNNING)) {
s.setInessential();
//s.setTransient();
s.setFlag(SshTool.PROP_CONNECT_TIMEOUT, Duration.TEN_SECONDS.toMilliseconds());
s.setFlag(SshTool.PROP_SESSION_TIMEOUT, Duration.THIRTY_SECONDS.toMilliseconds());
s.setFlag(SshTool.PROP_SSH_TRIES, 1);
}
if (groovyTruth(flags.get(USE_PID_FILE))) {
Object usePidFile = flags.get(USE_PID_FILE);
String pidFile = (usePidFile instanceof CharSequence ? usePidFile : Os.mergePathsUnix(getRunDir(), PID_FILENAME)).toString();
String processOwner = (String) flags.get(PROCESS_OWNER);
if (LAUNCHING.equals(phase)) {
entity.sensors().set(SoftwareProcess.PID_FILE, pidFile);
s.footer.prepend("echo $! > "+pidFile);
} else if (CHECK_RUNNING.equals(phase)) {
// old method, for supplied service, or entity.id
// "ps aux | grep ${service} | grep \$(cat ${pidFile}) > /dev/null"
// new way, preferred?
if (processOwner != null) {
s.body.append(
bashCommands().sudoAsUser(processOwner, "test -f "+pidFile) + " || exit 1",
"ps -p $(" + bashCommands().sudoAsUser(processOwner, "cat "+pidFile) + ")"
);
} else {
s.body.append(
"test -f "+pidFile+" || exit 1",
"ps -p `cat "+pidFile+"`"
);
}
// no pid, not running; 1 is not running
s.requireResultCode(Predicates.or(Predicates.equalTo(0), Predicates.equalTo(1)));
} else if (STOPPING.equals(phase)) {
String stopCommand = Joiner.on('\n').join("PID=$(cat "+pidFile + ")",
"test -n \"$PID\" || exit 0",
"SIGTERM_USED=\"\"",
"for i in $(seq 1 16); do",
" if ps -p $PID > /dev/null ; then",
" kill $PID",
" echo Attempted to stop PID $PID by sending SIGTERM.",
" else",
" echo Process $PID stopped successfully.",
" SIGTERM_USED=\"true\"",
" break",
" fi",
" sleep 1",
"done",
"if test -z $SIGTERM_USED; then",
" kill -9 $PID",
" echo Sent SIGKILL to $PID",
"fi",
"rm -f " + pidFile);
if (processOwner != null) {
s.body.append(bashCommands().sudoAsUser(processOwner, stopCommand));
} else {
s.body.append(stopCommand);
}
} else if (KILLING.equals(phase)) {
if (processOwner != null) {
s.body.append(
"export PID=$(" + bashCommands().sudoAsUser(processOwner, "cat "+pidFile) + ")",
"test -n \"$PID\" || exit 0",
bashCommands().sudoAsUser(processOwner, "kill -9 $PID"),
bashCommands().sudoAsUser(processOwner, "rm -f "+pidFile)
);
} else {
s.body.append(
"export PID=$(cat "+pidFile+")",
"test -n \"$PID\" || exit 0",
"kill -9 $PID",
"rm -f "+pidFile
);
}
} else if (RESTARTING.equals(phase)) {
if (processOwner != null) {
s.footer.prepend(
bashCommands().sudoAsUser(processOwner, "test -f "+pidFile) + " || exit 1",
"ps -p $(" + bashCommands().sudoAsUser(processOwner, "cat "+pidFile) + ") || exit 1"
);
} else {
s.footer.prepend(
"test -f "+pidFile+" || exit 1",
"ps -p $(cat "+pidFile+") || exit 1"
);
}
// no pid, not running; no process; can't restart, 1 is not running
} else {
log.warn(USE_PID_FILE + ": script option not valid for " + s.summary);
}
}
return s;
}