Created
February 28, 2011 15:45
-
-
Save lericson/847486 to your computer and use it in GitHub Desktop.
Gunicorn init script for Gentoo that checks liveliness properly
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/sbin/runscript | |
[[ -z "${PIDFILE}" ]] && PIDFILE="/var/run/gunicorn/${SVCNAME}.pid" | |
[[ -z "${BINARY}" ]] && BINARY="/usr/bin/gunicorn" | |
depend() { | |
need net | |
use dns logger netmount | |
} | |
check_params() { | |
if [[ "${SVCNAME}" == "gunicorn" && -z "${I_KNOW}" ]]; then | |
ewarn "It is highly recommended to use a symbolic link for this" | |
ewarn "script and start via that instead. This allows you to run" | |
ewarn "multiple spawn services simultaneously. To do this, simply:" | |
ewarn | |
ewarn " ln -s /etc/init.d/gunicorn /etc/init.d/gunicorn.mysvc" | |
ewarn " cp /etc/conf.d/gunicorn /etc/conf.d/gunicorn.mysvc" | |
ewarn | |
ewarn "If you don't want to be bothered by this message, set I_KNOW=yes" | |
ewarn "in your configuration file." | |
ewarn | |
fi | |
if [[ -z "${WSGI_APP}" ]] && [[ -z "${WSGI_TYPE}" ]]; then | |
eerror "${WSGI_APP} not set. Exiting" | |
return 1 | |
fi | |
if [[ -z "${PIDFILE}" ]]; then | |
eerror "PIDFILE must be set in /etc/conf.d/${SVCNAME}" | |
return 1 | |
fi | |
} | |
test_pidfile() { | |
if [[ ! -f "${PIDFILE}" ]]; then | |
eerror "${PIDFILE} does not exist" | |
return 1 | |
fi | |
read -r PID <"${PIDFILE}" | |
if [[ -z "${PID}" ]]; then | |
eerror "${PIDFILE} contains no PID" | |
return 1 | |
fi | |
if [[ ! -d "/proc/${PID}" ]]; then | |
eerror "${PID} does not appear to be an existing process" | |
return 1 | |
fi | |
if awk -F: 'BEGIN { found = 0; } END { exit(found); }; $1 == "State" && $2 !~ /^[[:space:]]*Z / { found = 1; };' "/proc/${PID}/status"; then | |
eerror "${PID} does not appear to be an active process" | |
return 1 | |
fi | |
return 0 | |
} | |
kill_pidfile() { | |
check_params && test_pidfile || return 1 | |
ebegin "$1" | |
shift | |
read -r PID <"${PIDFILE}" | |
kill "$@" "${PID}" | |
local RC=$? | |
eend $RC | |
return $RC | |
} | |
# actions | |
start() { | |
check_params || return 1 | |
local -a OPTS | |
OPTS=( "-c" "${CONFIG}" | |
"--daemon" | |
"--pid=${PIDFILE}" | |
"${WSGI_APP}" ) | |
ebegin "Starting ${SVCNAME} using ${CONFIG}" | |
env PYTHONPATH="${PYTHONPATH}" "${BINARY}" "${OPTS[@]}" | |
local RC=$? | |
eend "${RC}" | |
if [[ "${RC}" == 0 ]]; then | |
ebegin "No early errors, checking liveliness" | |
sleep 1 | |
if ! test_pidfile; then | |
eend 1 | |
return 1 | |
fi | |
eend 0 | |
fi | |
return "${RC}" | |
} | |
status() { | |
check_params && test_pidfile | |
} | |
stop() { | |
kill_pidfile "Stopping (gracefully) ${SVCNAME}" \ | |
-s SIGQUIT | |
} | |
force_stop() { | |
kill_pidfile "Stopping (disregarding jobs) ${SVCNAME}" \ | |
-s SIGINT | |
} | |
reload() { | |
kill_pidfile "Telling ${SVCNAME} to reload itself" \ | |
-s SIGHUP | |
} | |
opts="${opts} status reload force_stop" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use
Save as
/etc/init.d/gunicorn
Create a basic configuration at
/etc/conf.d/gunicorn
that says:Do as advised and create a symlink at
/etc/init.d/gunicorn.mysvc -> gunicorn
and copy the configuration template.Edit configuration, done.
Why would you use
Most init scripts suffer from the ailment that they don't actually know if the
daemon they control is living or not. This is a fundamental flaw, and the way
things are handled there is really no way to ascertain liveliness of Python
daemons because they run as the process "python", and
start-stop-daemon
relies on
pidof
and other dumb trickery. (Feel free to tell me off if youknow of a good way to do this with
start-stop-daemon
.)This script takes the stance that checking
/proc/$pid/status
isn't actuallyhard and can be done on a per-script basis. This yields the following desirable
behavior:
The init system is still a little dumb--it thinks the service is started even
though the status function returns non-zero--the script tells you something is
amiss. In this case the correct solution is to
zap
and start the serviceagain, since
stop
will fail due to there being no pidfile.