--- /dev/null
+#!/bin/bash
+#
+# Generic respawner for daemon processes.
+#
+# Created: Fri, 16 Apr 2004 17:40:36 +0200 zacchiro
+# Last-Modified: Fri, 16 Apr 2004 17:40:36 +0200 zacchiro
+#
+# by --Zack <zack@cs.unibo.it>
+#
+# Test to see if a daemon process (run via /etc/init.d/script) if still alive,
+# if not it respawns it using the corresponding init script. In order to check
+# if the daemon is still alive different predicates could be used:
+# 1) "ps" check with its pid
+# 2) http request to its url (if it's a web services)
+# all the available predicated can be enable or not (command line choice), all
+# the enabled predicates are ANDed. It's enough that one of them fails to
+# trigger daemon respawning.
+#
+# This respawner is supposed to be executed by "start" target of daemon's init.d
+# script.
+#
+# Sample /etc/init.d/foo script:
+#
+# DAEMON="/usr/sbin/foo"
+# PIDFILE="/var/run/$DAEMON.pid"
+# start)
+# echo -n "Starting $DAEMON"
+# start-stop-daemon \
+# --start --background --pidfile $PIDFILE --make-pidfile --exec $DAEMON
+# echo "."
+# echo -n "Starting $DAEMON respawner"
+# /home/zacchiro/bin/daemon_respawner.sh -p $PIDFILE \ -m root@localhost \
+# -r http://localhost:9999/bad -d `basename $0` &
+# echo "."
+# ;;
+# stop)
+# echo -n "Stopping $DAEMON respawner"
+# /home/zacchiro/bin/daemon_respawner.sh -d `basename $0` -s
+# echo "."
+# echo -n "Stopping $DAEMON"
+# start-stop-daemon --stop --pidfile $PIDFILE
+# rm -f $PIDFILE
+# echo "."
+# ;;
+# ...
+#
+
+# parse arguments
+TEMP=`getopt -o p:r:d:i:m:s --long pidfile:request:daemon:interval:mailto:stop -- "$@"`
+if [ $? != 0 ]; then
+ echo "Usage: ./daemon_respawner [-p|--pidfile <pidfile>] [-r|--request <url>] [-i|--interval <interval>] [-m|--mailto <mail>] -d|--daemon <daemon>"
+ echo " ./daemon_respawner -d|--daemon <daemon> -s|--stop"
+ exit 1
+fi
+PIDFILE=""
+REQUEST=""
+DAEMON=""
+INTERVAL="60"
+MAILTO=""
+STOP=""
+eval set -- "$TEMP"
+while true ; do
+ case "$1" in
+ -p|--pidfile) PIDFILE="$2"; shift 2 ;;
+ -r|--request) REQUEST="$2"; shift 2 ;;
+ -d|--daemon) DAEMON="$2"; shift 2 ;;
+ -i|--interval) INTERVAL="$2"; shift 2 ;;
+ -m|--mailto) MAILTO="$2"; shift 2 ;;
+ -s|--stop) STOP="yes"; shift ;;
+ --) shift; break ;;
+ esac
+done
+if [ -z "$DAEMON" ]; then
+ echo "No daemon provided: aborting."
+ exit 2
+fi
+MYPIDFILE="/var/run/$DAEMON""_respawner.pid"
+if ! [ -z "$STOP" ]; then # stop an active respawner and exit
+ if [ -r "$MYPIDFILE" ]; then
+ kill `cat "$MYPIDFILE"`
+ fi
+ rm -f "$MYPIDFILE"
+ exit 0
+fi
+if [ -z "$PIDFILE" -a -z "$REQUEST" ]; then
+ echo "Neither pidfile nor request URL was provided: aborting."
+ exit 2
+fi
+
+TIMEOUT="5" # timeout for http requests
+
+# usage: alert <subject> <body>
+alert ()
+{
+ if [ -z "$MAILTO" ]; then
+ echo "ALERT: $1"
+ echo "ALERT: $2"
+ echo
+ else
+ echo "$2" | mail -s "$1" $MAILTO
+ fi
+}
+
+# check if daemon is still alive
+daemon_is_alive ()
+{
+ IS_DEAD=""
+ if ! [ -z "$PIDFILE" ]; then # pid check enabled
+ if ! (ps `cat $PIDFILE` &> /dev/null); then # pid is no longer alive
+ IS_DEAD="true"
+ fi
+ fi
+ if ! [ -z "$REQUEST" ]; then # request check enabled
+ if ! (wget -T $TIMEOUT -O /dev/null "$REQUEST" &> /dev/null); then
+ # no answer
+ IS_DEAD="true"
+ fi
+ fi
+ test -z "$IS_DEAD"
+}
+
+# respawn daemon
+start_daemon ()
+{
+ rm -f "$MYPIDFILE"
+ invoke-rc.d $DAEMON stop
+ invoke-rc.d $DAEMON start &
+ exit 0 # the respawner will be restarted by daemon's init.d script
+}
+
+# first check
+sleep 1
+if ! daemon_is_alive; then
+ alert "$DAEMON failed to start :-((" "$DAEMON died during initialization :-((, enjoy debugging! :-P. Cheers."
+ exit 3
+fi
+# save pid
+echo $$ > "$MYPIDFILE"
+# continuous checks
+while true; do
+ sleep $INTERVAL
+ if ! daemon_is_alive; then
+ alert "$DAEMON died :-(, restarting it ..." "$DAEMON died miserably :-(. I'm going to try restarting it, you will receive an additional mail in case of failure. Cheers."
+ start_daemon # performed in background
+ fi
+done
+