#!/bin/sh # # quagga Starts/stops quagga daemons and watchquagga. # Create a daemon.conf file to have that routing daemon # started/stopped automagically when using this script # without any daemon names as args. # If watchquagga is available, it will also be # started/stopped if the script is called without # any daemon names. # ME=$(basename $0) usage() { echo "Usage: ${ME} {start|stop|restart} [daemon ...]" exit 2 } if [ -z "$1" ] then usage else COMMAND=$1 fi shift ARG_DAEMONS=$* BINDIR=/usr/sbin CONFDIR=/etc/quagga STATEDIR=/var/run/quagga RUNUSER=network RUNGROUP=$RUNUSER DAEMONS="zebra ripd ripngd ospfd ospf6d bgpd" DAEMON_FLAGS=-d WATCHQUAGGA_FLAGS="-d -z -T 60 -R" WATCHQUAGGA_CMD="$0 watchrestart" if [ ${COMMAND} != "watchrestart" -a -x "${BINDIR}/watchquagga" ] then DAEMONS="${DAEMONS} watchquagga" fi DAEMONS_STARTSEQ=${DAEMONS} reverse() { local revlist r revlist= for r do revlist="$r $revlist" done echo $revlist } DAEMONS_STOPSEQ=$(reverse ${DAEMONS_STARTSEQ}) #pidof() { # ps ax | awk 'match($5, "(^|/)'"$1"'$") > 0 { printf " %s", $1 }' #} quit() { echo "${ME}: $1" exit 0 } die() { echo "${ME}: $1" exit 1 } is_in() { local i for i in $2 do [ "$1" = "$i" ] && return 0 done return 1 } select_subset() { local unknown i j unknown= RESULT= for i in $1 do is_in $i "$2" || unknown="$unknown $i" done if [ -n "$unknown" ] then RESULT=$unknown return 1 else for j in $2 do is_in $j "$1" && RESULT="$RESULT $j" done return 0 fi } # check command case ${COMMAND} in start|stop|restart) ;; watchrestart) if [ -n "$ARG_DAEMONS" ] then echo "${ME}: watchrestart mode is only for use by watchquagga" exit 2 fi ;; *) usage ;; esac # select daemons to start case ${COMMAND} in start|restart|watchrestart) START_DAEMONS= for d in ${DAEMONS_STARTSEQ} do [ -x "${BINDIR}/${d}" -a -f "${CONFDIR}/${d}.conf" ] \ && START_DAEMONS="${START_DAEMONS}${d} " done WATCHQUAGGA_DAEMONS=${START_DAEMONS} if is_in watchquagga "${DAEMONS_STARTSEQ}" then START_DAEMONS="${START_DAEMONS} watchquagga" fi if [ -n "${ARG_DAEMONS}" ] then if select_subset "${ARG_DAEMONS}" "${DAEMONS}" then if select_subset "${ARG_DAEMONS}" "${START_DAEMONS}" then START_DAEMONS=${RESULT} else die "these daemons are not startable:${RESULT}." fi else die "unknown daemons:${RESULT}; choose from: ${DAEMONS}." fi fi ;; esac # select daemons to stop case ${COMMAND} in stop|restart|watchrestart) STOP_DAEMONS=${DAEMONS_STOPSEQ} if [ -n "${ARG_DAEMONS}" ] then if select_subset "${ARG_DAEMONS}" "${STOP_DAEMONS}" then STOP_DAEMONS=${RESULT} else die "unknown daemons:${RESULT}; choose from: ${DAEMONS}." fi fi stop_daemons= for d in ${STOP_DAEMONS} do pidfile=${STATEDIR}/${d}.pid if [ -f "${pidfile}" -o -n "$(pidof ${d})" ] then stop_daemons="${stop_daemons}${d} " elif [ -n "${ARG_DAEMONS}" ] then echo "${ME}: found no ${d} process running." fi done STOP_DAEMONS=${stop_daemons} ;; esac # stop daemons for d in $STOP_DAEMONS do echo -n "${ME}: Stopping ${d} ... " pidfile=${STATEDIR}/${d}.pid if [ -f "${pidfile}" ] then file_pid=$(cat ${pidfile}) if [ -z "${file_pid}" ] then echo -n "no pid file entry found ... " fi else file_pid= echo -n "no pid file found ... " fi proc_pid=$(pidof ${d}) if [ -z "${proc_pid}" ] then echo -n "found no ${d} process running ... " else count=0 notinpidfile= for p in ${proc_pid} do count=$((${count}+1)) if kill ${p} then echo -n "killed ${p} ... " else echo -n "failed to kill ${p} ... " fi [ "${p}" = "${file_pid}" ] \ || notinpidfile="${notinpidfile} ${p}" done [ ${count} -le 1 ] \ || echo -n "WARNING: ${count} ${d} processes were found running ... " for n in ${notinpidfile} do echo -n "WARNING: process ${n} was not in pid file ... " done fi count=0 survivors=$(pidof ${d}) while [ -n "${survivors}" ] do sleep 1 count=$((${count}+1)) survivors=$(pidof ${d}) [ -z "${survivors}" -o ${count} -gt 5 ] && break for p in ${survivors} do sleep 1 echo -n "${p} " kill ${p} done done survivors=$(pidof ${d}) [ -n "${survivors}" ] && \ if kill -KILL ${survivors} then echo -n "KILLed ${survivors} ... " else echo -n "failed to KILL ${survivors} ... " fi sleep 1 survivors=$(pidof ${d}) if [ -z "${survivors}" ] then echo -n "done." if [ -f "${pidfile}" ] then rm -f ${pidfile} \ || echo -n " Failed to remove pidfile." fi else echo -n "failed to stop ${survivors} - giving up." if [ "${survivors}" != "${file_pid}" ] then if echo "${survivors}" > ${pidfile} then chown ${RUNUSER}:${RUNGROUP} ${pidfile} echo -n " Wrote ${survivors} to pidfile." else echo -n " Failed to write ${survivors} to pidfile." fi fi fi echo done # start daemons if [ -n "$START_DAEMONS" ] then [ -d ${CONFDIR} ] \ || quit "${ME}: no config directory ${CONFDIR} - exiting." chown -R ${RUNUSER}:${RUNGROUP} ${CONFDIR} [ -d ${STATEDIR} ] || mkdir -p ${STATEDIR} \ || die "${ME}: could not create state directory ${STATEDIR} - exiting." chown -R ${RUNUSER}:${RUNGROUP} ${STATEDIR} for d in $START_DAEMONS do echo -n "${ME}: Starting ${d} ... " proc_pid=$(pidof ${d}) pidfile=${STATEDIR}/${d}.pid file_pid= if [ -f "${pidfile}" ] then file_pid=$(cat ${pidfile}) if [ -n "${file_pid}" ] then echo -n "found old pid file entry ${file_pid} ... " fi fi if [ -n "${proc_pid}" ] then echo -n "found ${d} running (${proc_pid}) - skipping ${d}." if [ "${proc_pid}" != "${file_pid}" ] then if echo "${proc_pid}" > ${pidfile} then chown ${RUNUSER}:${RUNGROUP} ${pidfile} echo -n " Wrote ${proc_pid} to pidfile." else echo -n " Failed to write ${proc_pid} to pidfile." fi fi elif rm -f "${pidfile}" then if [ "${d}" = "watchquagga" ] then "${BINDIR}/${d}" \ ${WATCHQUAGGA_FLAGS} \ "${WATCHQUAGGA_CMD}" \ ${WATCHQUAGGA_DAEMONS} status=$? else "${BINDIR}/${d}" ${DAEMON_FLAGS} status=$? fi if [ $status -eq 0 ] then echo -n "done." else echo -n "failed." fi else echo -n " failed to remove pidfile." fi echo done fi