Hi, I fixed two bugs in the script and am attaching the fixed version.
Fixed bugs: * No longer assume name of parent initscript is 2nd word of /proc/$PPID/cmdline. * When sending a service the kill signal, issue "sv d servicename" first because initscripts assume that the service will be down after a kill. Andras -- Andras Korn <korn at elan.rulez.org> There is no spoon(). Only a fork().
#!/bin/zsh # # This script is intended to wrap start-stop-daemon. It will call the # original start-stop-daemon with the supplied arguments unless the daemon # to be started appears to exist as a runit service, in which case it will # map the start-stop-daemon call to an sv(8) call. # # If called by non-root user, fall back to original start-stop-daemon # unconditionally [[ $UID -gt 0 ]] && exec /sbin/start-stop-daemon.real $@ set -A args $@ SVDIR=${SVDIR:-/etc/service} unset mode signal exec timeout startas testmode oknodo quiet verbose command svstat oknodo=0 quiet=0 while [[ -n "$1" ]]; do case "$1" in -S|--start) mode=start ;; -K|--stop) mode=stop ;; -T|--status) mode=status ;; -H|--help|-V|--version) exec /sbin/start-stop-daemon.real $args ;; -x|--exec) shift exec="$1" ;; -s|--signal) shift signal=$1 ;; --signal=*) signal="${1/--signal=/}" ;; -R|--retry) shift timeout="$1" ;; --retry=*) timeout="${1/--retry=/}" ;; -a|--startas) shift startas="$1" ;; -t|--test) testmode=1 ;; -o|--oknodo) oknodo=1 ;; -q|--quiet) quiet=1 exec >/dev/null ;; -v|--verbose) verbose=1 ;; -p|--pidfile|-n|--name|-u|--user|-g|--group|-r|--chroot|-d|--chdir|-N|--nicelevel|-P|--procsched|-I|--iosched|-k|--umask|-m|--make-pidfile) # ignored shift ;; --pidfile=*|-b|--background|--nicelevel=*|--procsched=*|--iosched=*|--umask=*) ;; --) # What follows is args to the daemon. Avoid parsing # those accidentally. break ;; *) # Assume the previous was the last option; the rest # is the name of the daemon plus args, of which we # only care about the daemon. command=$1 break ;; esac shift done # Try to infer runit service name. If our parent is an initscript, use its # basename read -A cmdline </proc/$PPID/cmdline while [[ -n "$cmdline[1]" ]]; do if [[ "${cmdline[1]:h}" = /etc/init.d ]]; then svname=${cmdline[1]:t} break fi shift cmdline done if [[ -z "$svname" ]] && [[ "${$(readlink -f /proc/$PPID/exe):h}" = /etc/init.d ]]; then read svname < /proc/$PPID/comm fi # if not, try other heuristics svnames=($startas $exec $command) while ! [[ -d $SVDIR/$svname/supervise/. ]] && [[ -n "$svnames[1]" ]]; do svname=${svnames[1]:t} shift svnames done # if runit service doesn't exist, call real start-stop-daemon. if ! [[ -d $SVDIR/$svname/supervise/. ]] || [[ -z "$svname" ]]; then exec /sbin/start-stop-daemon.real $args fi # otherwise, do what we've been asked to [[ "$quiet" = "0" ]] && [[ "$verbose" = "1" ]] && echo "start-stop-daemon.runit: will act on $svname service." >&2 function sendsig() { case "$signal" in HUP|1) sv hup $svname ;; INT|2) sv interrupt $svname ;; QUIT|3) sv quit $svname ;; KILL|9) sv d $svname sv kill $svname ;; USR1|10) sv 1 $svname ;; USR2|12) sv 2 $svname ;; ALRM|14) sv alarm $svname ;; TERM|15) sv down $svname ;; CONT|18) sv cont $svname ;; STOP|19) sv pause $svname ;; *) echo "$0: ERROR: don't know how to send $signal signal to $svname." >&2 exit 3 ;; esac } function wait_until_exited() { counter=0 read svstat < $SVDIR/$svname/supervise/stat while ! [[ "$svstat" = down ]]; do ((counter++)) [[ $counter -gt $timeout ]] && return 1 sleep 1 read svstat < $SVDIR/$svname/supervise/stat done return 0 } function do_stop() { if [[ $timeout =~ / ]]; then # handle complex schedule OLDIFS="$IFS" IFS=/ echo $timeout | read -A schedule IFS="$OLDIFS" while [[ -n "$schedule[1]" ]]; do signal=$schedule[1] sendsig shift schedule timeout=$schedule[1] wait_until_exited && exit 0 shift schedule done exit 2 else # simple timeout if [[ -z "$signal" ]]; then if [[ $timeout =~ ^[0-9]+$ ]]; then export SVWAIT=$timeout fi if sv stop $svname; then exit 0 else exit 1 fi else sendsig [[ -n "$timeout" ]] && if wait_until_exited; then exit 0 else exit 1 fi fi fi } read svstat < $SVDIR/$svname/supervise/stat case "$mode" in start) [[ "$svstat" = run ]] && [[ "$oknodo" = "0" ]] && exit 1 # Emulate start-stop-daemon semantics [[ -z "$testmode" ]] && sv start $svname exit 0 ;; stop) [[ "$svstat" = down ]] && [[ "$oknodo" = "1" ]] && exit 1 # Emulate start-stop-daemon semantics [[ -z "$testmode" ]] && do_stop # handles --retry and --signal, therefore separate function ;; status) case "$svstat" in # States are complex; we only handle the most basic cases here and bail on # the rest (e.g. "finish" cannot be correctly reported as "running" or "not # running") run) exit 0 ;; down) exit 3 ;; *) exit 4 ;; esac ;; esac exit 0