| #!/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 |