262 lines
6.6 KiB
Bash
Executable File
262 lines
6.6 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. By default this will create a python logging"
|
|
echo "configuration file in /etc/os-logging/servicename.conf"
|
|
echo ""
|
|
echo " -a Use alternate svc-map instead of map-services"
|
|
echo " -h Show help and exit"
|
|
echo " -p Print the job file instead of writing to disk"
|
|
echo " -l Create neither a python logging.conf nor pass --log-config-append argument to command."
|
|
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:-""}
|
|
DISABLE_LOGGING_CONF=
|
|
CREATE_DIR_NAME=${CREATE_DIR_NAME:-""}
|
|
# The default helps avoid race with daemon listening. http://pad.lv/1179766
|
|
POSTSTART=${POSTSTART:-$DEFAULT_POSTSTART}
|
|
MAPPING_COMMAND=map-services
|
|
|
|
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 "aplhd: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;;
|
|
a) MAPPING_COMMAND=svc-map;;
|
|
p) OUTPUT=print_only; APPEND=print_only;;
|
|
l) DISABLE_LOGGING_CONF="1";;
|
|
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
|
|
|
|
function deprecated_posarg_warning {
|
|
echo "WARNING: Setting $1 via positional argument is deprecated and will be removed in a future release."
|
|
}
|
|
|
|
# Compatibility with old style passing w/o switches
|
|
if [ -z "$SERVICENAME" ]; then
|
|
SERVICENAME=$1
|
|
shift
|
|
deprecated_posarg_warning "SERVICENAME"
|
|
fi
|
|
if [ -z "$RUNAS" ]; then
|
|
RUNAS=$1
|
|
shift
|
|
deprecated_posarg_warning "RUNAS"
|
|
fi
|
|
if [ -z "$RUNCMD" ]; then
|
|
CHECK=${1:-""}
|
|
if [ -n "$CHECK" ]; then
|
|
RUNCMD=$1
|
|
shift
|
|
deprecated_posarg_warning "CHECK"
|
|
fi
|
|
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
|
|
|
|
if [ -z "$DISABLE_LOGGING_CONF" ]; then
|
|
# Set up service-specific logging config
|
|
LOGGING_CONFIG="/etc/os-logging/$SERVICENAME.config"
|
|
mkdir /etc/os-logging || true
|
|
$OUTPUT $LOGGING_CONFIG <<EOF
|
|
[loggers]
|
|
keys=root
|
|
|
|
[handlers]
|
|
keys=syslog
|
|
|
|
[formatters]
|
|
keys=normal
|
|
|
|
[logger_root]
|
|
handlers=syslog
|
|
|
|
[handler_syslog]
|
|
class=handlers.SysLogHandler
|
|
args=('/dev/log', handlers.SysLogHandler.LOG_USER)
|
|
formatter=normal
|
|
|
|
[formatter_normal]
|
|
format=$SERVICENAME: %(asctime)s %(levelname)s %(message)s
|
|
EOF
|
|
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"
|
|
|
|
if [ -z "$DISABLE_LOGGING_CONF" ]; then
|
|
args="--log-config-append $LOGGING_CONFIG $args"
|
|
fi
|
|
|
|
$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 10s.
|
|
respawn limit 2 10
|
|
|
|
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
|
|
|
|
if [ -z "$DISABLE_LOGGING_CONF" ]; then
|
|
args="--log-config-append $LOGGING_CONFIG $args"
|
|
fi
|
|
|
|
$OUTPUT /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="$($MAPPING_COMMAND "$1")"
|
|
local user=$2
|
|
local dirname=${3:-$user}
|
|
|
|
$OUTPUT /lib/systemd/system/$name-create-dir.service <<EOF
|
|
[Unit]
|
|
Description=Create /var/run/$dirname
|
|
|
|
[Service]
|
|
ExecStartPre=/bin/mkdir -p /var/run/$dirname
|
|
ExecStartPre=/usr/local/bin/restore-selinux-file-context /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
|