/usr/sbin/radwatch is in freeradius 2.1.12+dfsg-1.2.
This file is owned by root:root, with mode 0o755.
The actual contents of the file can be viewed below.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 | #!/bin/sh
######################################################################
#
#    This program is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
#
#    Copyright (C) 2009 Network RADIUS SARL <info@networkradius.com>
#
######################################################################
#
# radwatch - Start the radius daemon and restart upon crash.
#
#  It also catches signals sent to it, and then re-sends those signals
#  to the radius server it is watching.
#
#  If you want to watch and re-start the server, we recommend
#  reading the file doc/supervise-radiusd.txt
#
#  This simplifies the script, and avoids most issues with (say)
#  Debian re-naming "radiusd" to "freeradius".
#
name=radiusd
prefix=/usr
exec_prefix=/usr
sbindir=${exec_prefix}/sbin
localstatedir=/var
logdir=/var/log/freeradius
rundir=${localstatedir}/run/${name}
sysconfdir=/etc
pid_file=${rundir}/${name}.pid
log_file=${logdir}/${name}_safe.log
#
#  Figure out what arguments to pass tail
#
tail="tail -n "
echo foo | ${tail}1 > /dev/null 2>&1
if test "$?" != "0"
then
    tail="tail -"
fi
RADIUSD=$sbindir/${name}
RADDBDIR=${sysconfdir}/raddb
#
#  If you want to send email, define this field to be an email address.
#  This part of the functionality hasn't been well tested, so please
#  test it before putting it into production.
#
#  It also presumes that you have a functioning mail system on
#  the maching running RADIUS.  You will need to check that the
#  "mail" command exists, and sends mail to the address below, e.g.:
#
#     echo test | mail -s "Testing" $MAILTO
#
#  If you receive the message, then enable MAILTO.  Otherwise, fix
#  your mail system so that it delivers mail.
#
MAILTO=
#
#  Allow "radiusd_safe -X" for testing the radiusd_safe functionality.
#
ARGS="$@"
test -f $RADIUSD || exit 0
test -f $RADDBDIR/radiusd.conf || exit 0
ulimit -c unlimited
#
#  See if the PID file exists.  It might have been left over after
#  a crash, or it might be because the RADIUS server is still running.
#
if test -f $pid_file
then
    PID=`cat $pid_file`
    #
    #  Check if the process exists, AND if it has the right name
    #
    if ps -p $PID | grep $name > /dev/null
    then
	echo "`date +'%a %b %e %H:%M:%S %Y'` : Fatal: A $name process already exists at PID $PID.  We cannot start another one." >> $log_file
	echo "A $name process already exists"
	exit 1
    fi
    
    #
    #  A RADIUS server doesn't exist.  Delete the stale PID file.
    #
    rm -f $pid_file
    if test -f $pid_file
    then
	echo "`date +'%a %b %e %H:%M:%S %Y'` : Fatal: Cannot remove the pid file: $pid_file" >> $log_file
	echo "Fatal error: Cannot remove the pid file: $pid_file"
	echo "Please remove it manually and start $0 again"
	echo "$name daemon not started"
	exit 1
    fi
fi
started=0
restarts=0
last_email=0
now=0
#
#  Save our PID.
#
echo $$ > ${rundir}/${name}_safe.pid
#
#  Loop forever, or until we're told to exit via a signal.
#
while :
do
    #
    #  The first time around, just start the server.
    #  After that, see if we are re-starting in the same second
    #  as the last time.  If so, sleep for a second.  Otherwise,
    #  if we're not starting in the same second, then just restart
    #  the server.
    #
    #  This helps prevent CPU spikes when something goes catastrophically
    #  wrong, and the server re-starts continuously.  (e.g. disk full, etc.)
    #
    now_s=`date +'%a %b %e %H:%M:%S %Y'`
    if test "$started" != "0"
    then
	#  Send mail when the server starts
	if test "$MAILTO" != ""
	then
	    # don't print minutes and seconds: cheap way
	    # of sending email only once an hour.
	    now=`date +'%a %b %e %H %Y'`
	    restarts=`expr $restarts + 1`
	    # send email the first time it restarts
	    if test "$last_email" = "0"
	    then
		    cat |  mail -s "ERROR - $name died, restarting.." $MAILTO <<EOF
$name has restarted unexpectedly at $now
See $log_file for details.  Last 20 lines are:
----------------------------------------------------------------------
`${tail}20 $log_file`
EOF
		last_email="$now"
		restarts=0
	    else
		#  Send email only once every hour (or so)
		if test "$now" != "$last_email"
		then
		    cat |  mail -s "ERROR - $name died, restarting.." $MAILTO <<EOF
$name has restarted $restarts times since last email at $last_email
See $log_file for details.  Last 100 lines are:
----------------------------------------------------------------------
`${tail}100 $log_file`
EOF
		    last_email="$now"
		    restarts=0
		fi
	    fi
	fi
	if test "$started" = "$now_s"
	then
	    #  Allow us to be killed
	    trap - HUP INT QUIT TERM TSTP
	    sleep 1
	fi
    fi
    started="$now_s"
    mysig=
    trap 'mysig=1' HUP
    trap 'mysig=2' INT
    trap 'mysig=3' QUIT
    trap 'mysig=15' TERM
    trap 'mysig=18' TSTP
    eval "$RADIUSD -f $ARGS < /dev/null >> $log_file 2>&1 &"
    PID=$!
    
    if test "$?" != "0"
    then
	echo "Failed to start $name.  See $log_file for details"
	echo "$name daemon not started"
	exit 1
    fi
    echo $PID > $pid_file
    #
    #  Wait for the process to exit.
    #
    wait $PID
    code=$?
    #
    #  On *BSD and Linux, sending *us* a signal results in "wait" returning
    #  with 128+sig.  On Solaris, it results in "wait" returning with "0".
    #
    #  If this happens, we reset our expectations here so that the code
    #  below will work correctly.
    #
    if test "$code" = "0"
    then
	if test "$mysig" != ""
	then
	    code=`expr $mysig + 128`
	fi
    fi
    case "$code" in
	0)
	    echo "`date +'%a %b %e %H:%M:%S %Y'` : Info: $name exited normally.  Exiting" | tee -a $log_file
	    break
	    ;;
	127)
	    echo "`date +'%a %b %e %H:%M:%S %Y'` : Info: $name exited unexpectedly.  Restarting it." | tee -a $log_file
	    ;;
	*)
	    #
	    #  The server exited of its own accord.
	    #
	    if test "$code" -lt 128
	    then
		echo "`date +'%a %b %e %H:%M:%S %Y'` : Info: $name exited unexpectedly on exit code $code.  Restarting it." | tee -a $log_file
	    else
		sig=`expr $code - 128`
		#
		#  Was the signal sent to us, or to the child process?
		#
		if test "$mysig" != ""
		then
		    echo "`date +'%a %b %e %H:%M:%S %Y'` : Info: Caught signal $sig: Signalling $name to exit." | tee -a $log_file
		    kill -$sig $PID
		    break
		else
		    echo "`date +'%a %b %e %H:%M:%S %Y'` : Info: $name exited unexpectedly on signal $sig.  Restarting it." | tee -a $log_file
		fi
	    fi
	    ;;
    esac
done
rm -f $pid_file ${rundir}/${name}_safe.pid
exit 0
 |