We are no longer piping our service output to logger, so we should be logging the stdout via upstart. This is useful for detecting tracebacks and other info which does not go through python logging. Change-Id: I5d4abb94ff15f74fd2478e70d0fa4d3bb9c09f2d
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
|