203 lines
4.9 KiB
Bash
Executable File
203 lines
4.9 KiB
Bash
Executable File
#!/bin/bash
|
|
set -eu
|
|
|
|
DEFAULT_POSTSTART="exec sleep 1"
|
|
|
|
usage() {
|
|
echo "Usage: os-svc-daemon [ -ph ] [ -s POSTSTART ] [ -e ENV ] -n SERVICENAME -u RUNAS [ -c RUNCMD -- [arg [arg...]]]"
|
|
echo ""
|
|
echo "SERVICENAME, RUNAS, RUNCMD, and POSTSTART can be set via the"
|
|
echo "environment as well. Command line arguments will override"
|
|
echo "environment variables."
|
|
echo ""
|
|
echo " -h Show help and exit"
|
|
echo " -p Print the job file instead of writing to disk"
|
|
echo " -d [NAME] Specify the name of the runtime directory, which will be"
|
|
echo " /var/run/[NAME]"
|
|
echo " -s POSTSTART post_start will be added to the upstart job. Ignored with systemd."
|
|
echo " default: $DEFAULT_POSTSTART"
|
|
echo " -e ENV Environment name=value entries to set in the service/job"
|
|
echo " -n SERVICENAME Name of job/service file."
|
|
echo " -i INSTALLDIR Optional: virtualenv installation directory. Defaults to: /opt/stack/venvs/<SERVICENAME>"
|
|
echo " -u RUNAS User to run main executable as."
|
|
echo " -c RUNCMD Command to execute. Must stay in foreground."
|
|
echo " arg... Arguments will be passed to COMMAND"
|
|
echo ""
|
|
}
|
|
|
|
# Can be set in environment now
|
|
SERVICENAME=${SERVICENAME:-""}
|
|
INSTALLDIR=
|
|
RUNAS=${RUNAS:-""}
|
|
RUNCMD=${RUNCMD:-""}
|
|
ENV=${ENV:-""}
|
|
CREATE_DIR_NAME=${CREATE_DIR_NAME:-""}
|
|
# The default helps avoid race with daemon listening. http://pad.lv/1179766
|
|
POSTSTART=${POSTSTART:-$DEFAULT_POSTSTART}
|
|
|
|
print_only() {
|
|
cat
|
|
}
|
|
|
|
print_to_file() {
|
|
cat > $1
|
|
}
|
|
|
|
append_to_file() {
|
|
cat >> $1
|
|
}
|
|
|
|
OUTPUT=print_to_file
|
|
APPEND=append_to_file
|
|
|
|
nshift=0
|
|
while getopts "phd:s:n:i:u:c:e:" opt; do
|
|
case "$opt" in
|
|
n) SERVICENAME=$OPTARG;;
|
|
i) INSTALLDIR=$OPTARG;;
|
|
u) RUNAS=$OPTARG;;
|
|
c) RUNCMD=$OPTARG;;
|
|
s) POSTSTART=$OPTARG;;
|
|
e) ENV=$OPTARG;;
|
|
p) OUTPUT=print_only; APPEND=print_only;;
|
|
d) CREATE_DIR_NAME=$OPTARG;;
|
|
h) usage; exit 0;;
|
|
\?) usage; exit 1;;
|
|
:) usage; exit 1;;
|
|
esac
|
|
done
|
|
|
|
shift $(($OPTIND-1))
|
|
if [ -z "$SERVICENAME" ] || [ -z "$RUNAS" ] ; then
|
|
if [ $# -lt 3 ] ; then
|
|
usage
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
# Compatibility with old style passing w/o switches
|
|
[ -n "$SERVICENAME" ] || { SERVICENAME=$1 ; shift; }
|
|
[ -n "$RUNAS" ] || { RUNAS=$1 ; shift; }
|
|
if [ -z "$RUNCMD" ]; then
|
|
CHECK=${1:-""}
|
|
[ -n "$CHECK" ] && { RUNCMD=$1 ; shift; }
|
|
fi
|
|
|
|
# if INSTALLDIR isn't set use /opt/stack/venvs/RUNAS
|
|
# NOTE: this was our default before adding the -i option
|
|
if [ -z "$INSTALLDIR" ]; then
|
|
INSTALLDIR="/opt/stack/venvs/$RUNAS"
|
|
fi
|
|
|
|
function install_upstart {
|
|
local name=$1
|
|
local install_dir=$2
|
|
local user=$3
|
|
local dirname=${4:-$user}
|
|
local cmd=$5
|
|
shift; shift; shift; shift; shift
|
|
local args=$*
|
|
|
|
local env_entries=''
|
|
if [ -n "$ENV" ]; then
|
|
local env_pad=" $ENV"
|
|
env_entries=${env_pad// /
|
|
env }
|
|
fi
|
|
local target_file="/etc/init/$name.conf"
|
|
|
|
$OUTPUT $target_file <<EOF
|
|
start on runlevel [2345]
|
|
stop on runlevel [016]
|
|
$env_entries
|
|
|
|
env OS_SVC_ENABLE_CONTROL=1
|
|
export OS_SVC_ENABLE_CONTROL
|
|
|
|
pre-start script
|
|
mkdir -p /var/run/$dirname
|
|
chown -R $user:$user /var/run/$dirname
|
|
end script
|
|
EOF
|
|
|
|
if [ -n "$cmd" ]; then
|
|
$APPEND $target_file <<EOF
|
|
|
|
respawn
|
|
# the default post-start of 1 second sleep delays respawning enough to
|
|
# not hit the default of 10 times in 5 seconds. Make it 2 times in 5s.
|
|
respawn limit 2 5
|
|
|
|
exec start-stop-daemon --start -c $user --exec $install_dir/bin/$cmd -- $args
|
|
|
|
post-start $POSTSTART
|
|
EOF
|
|
fi
|
|
}
|
|
|
|
function install_systemd {
|
|
local name=$1
|
|
local install_dir=$2
|
|
local user=$3
|
|
local cmd=$4
|
|
shift; shift; shift; shift;
|
|
local args=$*
|
|
|
|
local env_entries=''
|
|
if [ -n "$ENV" ]; then
|
|
local env_pad=" $ENV"
|
|
env_entries=${env_pad// /
|
|
Environment=}
|
|
fi
|
|
|
|
$OUTPUT /usr/lib/systemd/system/$name.service <<EOF
|
|
[Unit]
|
|
Description=$name Service
|
|
After=os-refresh-config.service
|
|
Requires=$name-create-dir.service
|
|
|
|
[Service]
|
|
ExecStart=$install_dir/bin/$cmd $args
|
|
User=$user
|
|
$env_entries
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
Alias=$name.service
|
|
EOF
|
|
|
|
}
|
|
|
|
function install_create_dir_systemd {
|
|
local name=$(map-services $1)
|
|
local user=$2
|
|
local dirname=${3:-$user}
|
|
|
|
$OUTPUT /usr/lib/systemd/system/$name-create-dir.service <<EOF
|
|
[Unit]
|
|
Description=Create /var/run/$dirname
|
|
|
|
[Service]
|
|
ExecStartPre=/bin/mkdir -p /var/run/$dirname
|
|
ExecStart=/bin/chown -R $user:$user /var/run/$dirname
|
|
|
|
[Install]
|
|
RequiredBy=$name.service
|
|
EOF
|
|
|
|
}
|
|
|
|
# TODO: SysV init fallback support
|
|
DIB_INIT_SYSTEM=$(dib-init-system)
|
|
if [ "$DIB_INIT_SYSTEM" == "upstart" ]; then
|
|
install_upstart $SERVICENAME $INSTALLDIR $RUNAS "$CREATE_DIR_NAME" "$RUNCMD" $*
|
|
elif [ "$DIB_INIT_SYSTEM" == "systemd" ]; then
|
|
if [ "$POSTSTART" != "$DEFAULT_POSTSTART" ] ; then
|
|
echo "WARNING: post start is ignored with systemd." >&2
|
|
fi
|
|
if [ -n "$RUNCMD" ]; then
|
|
install_systemd $SERVICENAME $INSTALLDIR $RUNAS $RUNCMD $*
|
|
fi
|
|
install_create_dir_systemd $SERVICENAME $RUNAS $CREATE_DIR_NAME
|
|
fi
|