#! /bin/sh
#
# chkconfig: - 98 10
# description: Condor HTC computing platform
#
# condor script for SysV-style init boot scripts.
#
# Usually this would be installed as /etc/init.d/condor with soft
# links put in from /etc/rc*.d to point back to /etc/init.d/condor to
# determine when Condor should be started and stopped. Exact
# directories or details of the links you should use will vary from
# platform to platform.
#
# This script strives for portability, and thus may be inelegant
# on any given system. Users on Fedora or Red Hat systems should
# also consider "condor.init", which is more native and should
# integrate better with the rest of the system.
# LSB init part (Used by Debian package)
### BEGIN INIT INFO
# Provides: condor
# Required-Start: $network $local_fs $remote_fs
# Required-Stop: $remote_fs $local_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Manage condor daemons
# Description: Condor HTC computing platform
### END INIT INFO
######################################################################
## Ensure that the settings below are correct for your Condor
## installation. Except for SYSCONFIG, these may also be specified
## in the "$SYSCONFIG/condor" file.
# Directory with system configuration files
#SYSCONFIG="/etc/sysconfig"
# Condor's sysconfig file
#CONDOR_SYSCONFIG="/etc/sysconfig/condor"
# Condor users to look for while shutting down.
#CONDOR_USERS="condor,root"
# Path to your primary condor configuration file.
#CONDOR_CONFIG="/etc/condor/condor_config"
# Path to condor_config_val
#CONDOR_CONFIG_VAL="/usr/bin/condor_config_val"
# How long to give Condor to shut down cleanly?
#MAX_STOP_WAIT=300
# Disable the use of a 'PID file?
#DISABLE_PIDFILE="no"
# Only kill Condor PIDs from the PID file
#FORCE_PIDFILE="no"
## There are no settings beyond this point.
######################################################################
# Source LSB init function. This will allow for, e.g., systemd to smoothly
# redirect init script calls to systemctl
. /lib/lsb/init-functions
# help & usage
myusage() {
echo "usage: $1 [options] command"
}
myhelp() {
myusage
echo " --no-execute, -n : No execute mode"
echo " --execute : Execute mode (default)"
echo " --verbose, -v : Verbose mode"
echo " --sysconfig
: Specify the sysconfig directory"
echo "Environment variables:"
echo " SYSCONFIG : Specify the sysconfig directory"
echo " CONDOR_SYSCONFIG : Specify Condor's sysconfig file"
echo " CONDOR_CONFIG : Specify path to Condor's configuration file"
echo " CONDOR_CONFIG_VAL : Specify path to condor_config_val"
echo "Commands: start stop restart try-restart reload force-reload status"
}
# Process command line arguments
# Looks through argv, pick out ones that start with a dash,
# and handle them
EXECUTE=yes
VERBOSE=no
while [ $# -gt 0 ] ; do
c=`expr $1 : '\(.\).*'`
if [ "$c" != "-" ] ; then
break
fi
case "$1" in
"-n" | "--no-execute" )
EXECUTE=no
shift
;;
"--execute" )
EXECUTE=yes
shift
;;
"-v" | "--verbose" )
VERBOSE=yes
shift
;;
"--sysconfig" )
SYSCONFIG=$2
shift; shift
;;
"-h" | "--help" )
myhelp
exit 0
;;
* )
myusage
echo "Unkown option: $1: use --help for help"
exit 1
;;
esac
done
INIT_COMMAND=$1
################################################################################
# Read in the sysconfig file
if [ "$SYSCONFIG" = "" ] ; then
SYSCONFIG=/etc/sysconfig
fi
if [ "$CONDOR_SYSCONFIG" = "" ] ; then
CONDOR_SYSCONFIG=$SYSCONFIG/condor
fi
[ -f "$CONDOR_SYSCONFIG" ] && . "$CONDOR_SYSCONFIG"
# Default condor configuration file if none specified
if [ "$CONDOR_CONFIG" = "" ] ; then
CONDOR_CONFIG=/etc/condor/condor_config
fi
# Default path condor_config_val if none specified
if [ "$CONDOR_CONFIG_VAL" = "" ] ; then
CONDOR_CONFIG_VAL=/usr/bin/condor_config_val
fi
# Default value to max shutdown wait
if [ "$MAX_STOP_WAIT" = "" ] ; then
MAX_STOP_WAIT=300
fi
if [ "$USER" = "" ] ; then
USER=`whoami`
fi
# A key goal of this script is portability. As a result,
# there are is awkward syntax. For example: the -e test
# for file existance isn't available in Solaris 9 /bin/sh
# so "\( -f "$1" -o -L "$1" \)" is used as a rough equivalent.
# stop is not an acceptable function name on AIX and HPUX,
# so the function is called xstop.
# Equivalent to "echo -n", but portable.
echon() {
if [ "`echo -n`" = "-n" ]; then
echo "$@""\c"
else
echo -n "$@"
fi
}
# Emits error with a "FATAL: " prefix. Exits. Never returns
fatal_error() {
echo "FATAL: $1"
exit 1
}
##
## Try to detect a binary from set of names and set of directories.
## Note: The names and directories cannot contain whitespace, because
## whitespace is the the list delimiter.
##
detect_exe() {
for name in `echo $2` ; do
for dir in `echo $1` ; do
if [ -x "$dir/$name" ] ; then
echo "$dir/$name"
return
fi
done
done
}
##
## Based on the ps flavor ($1), return the ps options
##
ps_get_opts() {
if [ "$1" = "GNU" -o "$1" = "BSD" ] ; then
opts="aux"
elif [ "$1" = "SYSV" ] ; then
opts="-ef"
else
echo "FATAL: Unknown ps flavor \"$1\""
exit 1
fi
echo $opts
}
##
## Try to run ps, see if it fails
##
ps_try_run() {
cmd="$1 $2"
$cmd > /dev/null 2>&1
if [ $? -eq 0 ] ; then
echo "yes"
else
echo "no"
fi
}
##
## Detect the 'ps' (in $PS) executable's flavor
##
ps_detect_flavor() {
if [ "$1" = "GNU" ] ; then
OPTS="--version"
else
OPTS=`ps_get_opts "$1"`
fi
STATUS=`ps_try_run "$PS" "$OPTS"`
echo $STATUS
}
##
## Detect ps support extra flags ('w' and 'n')
##
ps_detect_flags() {
if [ "$PSFLAVOR" = "GNU" ] ; then
PSFLAGSn="n"
PSFLAGSw="www"
return
fi
OPTS=`ps_get_opts "$PSFLAVOR"`
OPTS="${OPTS}www"
OK=`ps_try_run "$PS" "$OPTS"`
if [ "$OK" = "yes" ] ; then
PSFLAGSw="www"
fi
OPTS=`ps_get_opts "$PSFLAVOR"`
OPTS="${OPTS}n"
OK=`ps_try_run "$PS" "$OPTS"`
if [ "$OK" = "yes" ] ; then
PSFLAGSn="n"
fi
}
##
## Detect the 'ps' exectuable and it's flavor
##
detect_ps() {
DIRS="/usr/gnu/bin /usr/local/bin /opt/freeware/bin /usr/ucb /usr/bin /bin"
NAMES="ps"
PS=`detect_exe "${DIRS}" "${NAMES}"`
if [ "$PS" = "" ] ; then
echo "FATAL: no ps binary detected"
exit 1
fi
for FLAVOR in GNU SYSV BSD ; do
if [ "$PSFLAVOR" = "" ] ; then
OK=`ps_detect_flavor $FLAVOR`
if [ "$OK" = "yes" ] ; then
PSFLAVOR="$FLAVOR"
fi
fi
done
if [ "$PSFLAVOR" = "" ] ; then
echo "FATAL: Unable to detect the flavor of \"$PS\""
exit 1
fi
if [ "$VERBOSE" = "yes" ] ; then
echo "Detected ps executable \"$PS\" flavor \"$PSFLAVOR\", flags: $PSFLAGSw $PSFLAGSn"
fi
}
##
## Detect awk flavor
## returns: GNU NAWK XPG4 AWK
##
detect_awk_flavor() {
awk=$1
# GNU
out=`echo ""|$awk --version 2>/dev/null | grep GNU`
if [ "$out" != "" ] ; then
echo "GNU"; return 0
fi
out=`echo "abc"|$awk '{ sub(/abc/,"ABC"); print; }'` 2>/dev/null
if [ "$?" != 0 ] ; then
echo "AWK"; return 0
fi
out=`echo "x=4"|$awk '{ s=$1; sub(/x=([0-9]+).*/, "\1", s); print s; }'`
if [ "$out" = "x=4" ] ; then
echo "XPG4"; return 0
fi
echo "NAWK"; return 0
}
##
## Detect awk and it's flavor
##
detect_awk() {
if [ "$AWK" != "" ] ; then
return 0
fi
DIRS="/usr/gnu/bin /usr/local/bin /usr/xpg4/bin /opt/freeware/bin /usr/ucb /usr/bin /bin"
NAMES="gawk nawk awk"
AWK=`detect_exe "$DIRS" "$NAMES"`
if [ "$AWK" = "" ] ; then
echo "FATAL: no awk binary detected"
exit 1
fi
AWKFLAVOR=`detect_awk_flavor $AWK`
if [ "$AWKFLAVOR" = "" ] ; then
echo "FATAL: Unable to detect the flavor of \"$AWK\""
exit 1
fi
if [ "$VERBOSE" = "yes" ] ; then
echo "Detected awk executable \"$AWK\" flavor \"$AWKFLAVOR\""
fi
}
# Is the executable in $1 potentially runnable?
# Exit if no.
verify_executable() {
if [ ! \( -f "$1" -o -L "$1" \) ]; then
fatal_error "Required executable $1 does not exist."
fi
if [ -d "$1" ]; then
fatal_error "Required executable $1 is a directory instead of a file."
fi
if [ ! -x "$1" ]; then
fatal_error "Required executable $1 is not executable."
fi
return 0
}
# Is the path in $1 a potentially readable directory?
# Exit if no.
verify_readable_directory() {
if [ ! -d "$1" ]; then
fatal_error "Required directory $1 does not exist, or is not a directory."
fi
if [ ! -r "$1" ]; then
fatal_error "Required executable $1 is not readable."
fi
return 0
}
# Returns a setting from the CONDOR_CONFIG configuration
# file. Exits if the value cannot be found!
get_condor_config_val() {
REQUIRED=$2
if [ "$REQUIRED" = "" ] ; then
REQUIRED=yes
fi
TMPVAL=`"$CONDOR_CONFIG_VAL" $1 2>/dev/null`
if [ "$TMPVAL" = "" ] && [ "$REQUIRED" = "yes" ] ; then
fatal_error "Unable to locate $1 in $CONDOR_CONFIG"
fi
echo "$TMPVAL"
}
# Ensure CONDOR_SBIN holds path to SBIN as defined in the
# CONDOR_CONFIG file
set_condor_sbin() {
if [ "$CONDOR_SBIN" != "" ]; then
return 0;
fi
CONDOR_SBIN=`get_condor_config_val SBIN`
verify_readable_directory "$CONDOR_SBIN"
return 0;
}
# Ensure CONDOR_RUN holds path to a plausible run directory.
# Exit on failure.
set_condor_run() {
if [ "$CONDOR_RUN" != "" ]; then
return 0
fi
CONDOR_RUN=`get_condor_config_val RUN no`
if [ "$CONDOR_RUN" = "" ]; then
CONDOR_RUN=`get_condor_config_val LOG yes`
fi
if [ ! -d "$CONDOR_RUN" ] ; then
mkdir "$CONDOR_RUN"
if [ "$USER" = "root" -a "$CONDOR_USER" != "" ] ; then
chown "$CONDOR_USER" "$CONDOR_RUN"
fi
fi
verify_readable_directory "$CONDOR_RUN"
return 0
}
# Ensure CONDOR_MASTER holds path to a plausible condor_master.
# Exit on failure.
set_condor_master() {
if [ "$CONDOR_MASTER" = "" ]; then
CONDOR_MASTER=`get_condor_config_val MASTER`
fi
verify_executable "$CONDOR_MASTER"
return 0
}
# Ensure CONDOR_RECONFIG holds path to a plausible condor_reconfig.
# Exit on failure.
set_condor_reconfig() {
if [ "$CONDOR_RECONFIG" = "" ]; then
set_condor_sbin
CONDOR_RECONFIG="$CONDOR_SBIN/condor_reconfig"
fi
verify_executable "$CONDOR_RECONFIG"
return 0
}
# Set CONDOR_USERS
set_condor_users() {
CONDOR_USERS=""
CONDOR_USER="$1"
while [ "$1" != "" ] ; do
if [ "$CONDOR_USERS" != "" ] ; then
CONDOR_USERS="$CONDOR_USERS,$1"
else
CONDOR_USERS="$1"
fi
shift
done
}
# Get the condor user(s)
detect_condor_users() {
if [ "$CONDOR_USERS" != "" ]; then
return 0
fi
if [ "$USER" != "root" -a "$USER" != "condor" ] ; then
MYUSER="$USER"
fi
IDS=`get_condor_config_val CONDOR_IDS no`
if [ "$IDS" = "" ]; then
set_condor_users "condor" "root" "$MYUSER"
return 0
fi
TMP_USER=`echo $IDS|$AWK 'BEGIN{FS="[ ,.]"} /^[^0-9]/{print $1}'`
if [ "$TMP_USER" != "" ] ; then
set_condor_users "$TMP_USER" "root" "$MYUSER"
return 0
fi
CONDOR_UID=`echo $IDS|$AWK 'BEGIN{FS="[ ,.]"} /^[0-9]/{print $1}'`
for u in condor ; do
TMP_UID=`id $u|$AWK '{ sub(/uid=/,"",$1); sub(/\(.*\)/,"",$1); print $1; }'`
if [ "$TMP_UID" = "$CONDOR_UID" ] ; then
set_condor_users "$u" "root" "$MYUSER"
return 0
fi
done
TMP_USER=`cat /etc/passwd|$AWK 'BEGIN{FS=":"; UID=ARGV[1]; ARGC=0; } { if($3==UID){print $1} }' $CONDOR_UID`
if [ "$TMP_USER" != "" ] ; then
echo "$TMP_USER had uid $CONDOR_UID"
set_condor_users "$TMP_USER" "root" "$MYUSER"
return 0
fi
CONDOR_USER="$CONDOR_UID"
CONDOR_UIDS="$CONDOR_UID,0"
return 0
}
# Ensure CONDOR_OFF holds path to a plausible condor_off.
# Exit on failure.
set_condor_off() {
if [ "$CONDOR_OFF" = "" ]; then
set_condor_sbin
CONDOR_OFF="$CONDOR_SBIN/condor_off"
fi
verify_executable "$CONDOR_OFF"
return 0
}
##
## Find the Condor master processes
##
find_masters() {
if [ "$CONDOR_USERS" = "" ] ; then
OPTS=`ps_get_opts "$PSFLAVOR" "W" "N"`
TMP_USERS=$CONDOR_UIDS
else
OPTS=`ps_get_opts "$PSFLAVOR" "W"`
TMP_USERS=$CONDOR_USERS
fi
pids=`$PS $OPTS|$AWK 'BEGIN{split(ARGV[1],users,","); ARGC=0; } { if( (index($0,"condor_master") != 0) && (index($0,"awk") == 0) ) { for(i in users){ if($1==users[i]){print $2; break;} } } }' $TMP_USERS`
echo "$pids"
}
# To the best of its ability, finds the active condor_master's PID.
# Store the result in global variable MASTER_PIDS.
# You can call this repeatedly to check for updates.
# If we use the pid file the first time through, always use it --
# if it disappears, means that the Condor went bye-bye
condor_master_pids() {
masterpid=
if [ -f "$PIDFILE" -a -r "$PIDFILE" ] ; then
masterpid=`cat "$PIDFILE"` 2>/dev/null
# validate PID
`kill -0 $masterpid` > /dev/null
if [ $? -eq 0 ] ; then
FORCE_PIDFILE="yes"
else
masterpid=""
# Remove the stale pidfile
rm -f $PIDFILE
fi
fi
if [ "$FORCE_PIDFILE" = "yes" ] ; then
MASTER_PIDS="$masterpid"
return 0
fi
pids=`find_masters`
if [ "$masterpid" = "" ] ; then
MASTER_PIDS="$pids"
if [ "$pids" = "" ] ; then return 1; else return 0; fi
fi
echo "$pids" | grep -w "$masterpid" > /dev/null
if [ $? -eq 0 ] ; then
MASTER_PIDS="$masterpid"
return 0
fi
foundpid=`$PS | grep condor_master | grep -v grep | $AWK '{print $2}' | grep "^$masterpid$"`
if [ "$foundpid" = "" ]; then
MASTER_PIDS="$foundpid"
if [ "$pids" = "" ] ; then return 1; else return 0; fi
fi
MASTER_PIDS="$masterpid"
return 0
}
# Wait for condor_master to exit.
#
# Only reliably detects condor_masters started by this script
#
# Sleeps $1 seconds between checks
# After approximately $2 seconds, gives up
#
# $?=0 - condor_master is gone
# $?=1 - timed out
wait_for_exit() {
if [ "$VERBOSE" = "yes" ] ; then
echo "Waiting for Condor to stop (MAX: $2 seconds)"
fi
sleep_time=$1
max_wait=$2
stop_duration=0
condor_master_pids
while [ "$MASTER_PIDS" != "" -a $stop_duration -lt $max_wait ]; do
if [ "$VERBOSE" = "yes" ] ; then
echo "Still waiting on $MASTER_PIDS"
fi
sleep $sleep_time
stop_duration=`expr $stop_duration + $sleep_time`
condor_master_pids
done
if [ "$MASTER_PIDS" = "" ]; then
return 0
else
return 1
fi
}
# Start condor.
start() {
set_condor_master
if [ "$VERBOSE" = "yes" ] ; then
echo "Starting up Condor..."
else
echon "Starting up Condor... "
fi
if [ "$EXECUTE" != "yes" ] ; then
echo "skipping."
return 0
fi
if [ "$CONDOR_MASTER_WRAPPER" = "" ] ; then
if [ "$PIDFILE" = "" ] ; then
cmd="$CONDOR_MASTER"
"$CONDOR_MASTER"
else
cmd="$CONDOR_MASTER -pidfile $PIDFILE"
"$CONDOR_MASTER" -pidfile "$PIDFILE"
fi
else
cmd="$CONDOR_MASTER_WRAPPER"
"$CONDOR_MASTER_WRAPPER"
fi
if [ $? -ne 0 ]; then
echo " failed to start Condor with \"$cmd\"."
return 1;
fi
if [ "$VERBOSE" = "yes" ] ; then
echo "Started: \"$cmd\""
if [ "$PIDFILE" != "" ] ; then
seconds=0
while [ ! -f "$PIDFILE" -a $seconds -lt 10 ]; do
sleep 1
seconds=`expr $seconds + 1`
done
if [ -f "$PIDFILE" ] ; then
echon "Master PID = ";
cat "$PIDFILE"
fi
fi
fi
echo "done."
return 0
}
# Tries to stop the condor_master
#
# If we have a valid PIDFILE, uses "kill -QUIT".
# Failing that, uses "condor_off -fast -master"
#
# We prefer the "kill -QUIT", as the master might refuse
# the condor_off request because of security configuration.
# We still try condor_off in case the PIDFILE is missing,
# say because someone started condor_master by hand.
#
# The two options are nearly identical from the condor_master's
# point of view; it will end up executing the same shutdown
# code either way.
#
# named xstop because stop causes problems on AIX and HPUX.
xstop() {
if [ "$VERBOSE" = "yes" ] ; then
echo "Shutting down Condor (fast-shutdown mode)..."
else
echon "Shutting down Condor (fast-shutdown mode)... "
fi
condor_master_pids
if [ "$MASTER_PIDS" != "" ]; then
if [ "$EXECUTE" != "yes" ] ; then
echo "Skipping."
return 0
fi
for pid in `echo "$MASTER_PIDS"` ; do
if [ "$VERBOSE" = "yes" ] ; then
echo "Sending QUIT to $pid"
fi
kill -QUIT "$pid"
done
# We assume that user will use init script to startup/shutdown
# condor only, so we will rely on the pid file. condor_off cannot
# differentiate between fail to stop condor or condor is not
# running, so we don't use it for now.
fi
wait_for_exit 1 $MAX_STOP_WAIT
if [ $? -gt 0 ]; then
echo "Failed to stop Condor (timed out)."
return 1
fi
if [ -f "$PIDFILE" ]; then
rm "$PIDFILE"
fi
echo "done."
return 0
}
# Ask Condor to re-read its configuration files
#
# This can fail for any number of reasons, and we wouldn't
# detect it.
#
# As a possible improvement, we might send SIGHUP if condor_master_pids
# finds nothing, only falling back on condor_reconfig if it is.
#
# Also, detect the return code from CONDOR_RECONFIG; non-zero
# indicates aproblem. (At the moment that never happens, but
# may in the future.)
reload() {
set_condor_reconfig
echon "Reloading Condor configuration..."
"$CONDOR_RECONFIG" | grep -v 'Sent "Reconfig" command to local master'
echo "done."
return 0
}
# Report Condor's status
#
# If condor was started by directly running condor_master,
# this will erroneously report that it is not running.
#
# Return codes (from Linux Standards Base)
# (Not all of these are currently implemented)
# 0 running
# 1 dead and /var/run pid file exists
# 2 dead and /var/lock lock file exists
# 3 not running
# 4 unknown
status() {
condor_master_pids
master_pid="$MASTER_PIDS"
if [ "$master_pid" != "" ]; then
echo "Condor is running (pid $master_pid)"
return 0
else
echo "Condor is not running"
return 3;
fi
}
verify_executable "$CONDOR_CONFIG_VAL"
# We don't use CONDOR_CONFIG directly, it's used by the
# Condor tools.
if [ "$CONDOR_CONFIG" != "" ]; then
export CONDOR_CONFIG
fi
detect_ps
detect_awk
detect_condor_users
if [ "$CONDOR_USERS" = "" ] ; then
if [ "$PSFLAGSn" = "" ] ; then
fatal_error "CONDOR_IDS is \"$IDS\", and I can't detect what user that maps to.\n Specify CONDOR_USERS in your Condor sysconfig file ($CODNOR_SYSCONFIG, if it exists)\n or at the top of this script."
fi
fi
# PID file overides / fallbacks
if [ "$DISABLE_PIDFILE" = "yes" ] ; then
PIDFILE=""
elif [ "$PIDFILE" = "" ] ; then
set_condor_run
PIDFILE="$CONDOR_RUN/condor.pid"
fi
if [ "$INIT_COMMAND" = "" ] ; then
myhelp
exit 1
fi
case "$INIT_COMMAND" in
'start')
start
;;
'stop')
xstop
;;
'restart')
xstop
start
;;
'try-restart')
condor_master_pids
if [ "$MASTER_PIDS" = "" ]; then exit 0; fi # Not running
xstop
start
;;
'reload')
reload
;;
'force-reload')
reload
;;
'status')
status
;;
*)
echo "Unknown command $INIT_COMMAND: use --help for help"
exit 1
;;
esac