1#!/bin/sh 2# 3# $Header: /usr/local/src/dhcp_probe-latest/extras/RCS/site-application-dhcp_probe,v 1.1 2011/12/14 20:32:03 root Exp root $ 4# 5# This is a Solaris SMF method script (a startup script) for the dhcp_probe daemon. 6# 7# Usage: 8# site-application-dhcp_probe [-v] -i interface [-Q vlan_id|none] [-r] [-d debuglevel] start 9# site-application-dhcp_probe [-v] -i interface stop contract_id 10# 11# -d debuglevel call dhcp_probe with '-d debuglevel' overridding default DEBUG_OPT constant below. 12# -i interface name of network interface on which to run 13# -Q vlan_id call dhcp_probe with '-Q vlan_id' 14# -r rotate capture files before starting daemon 15# -v enable verbosity 16# 17# 18# When starting, if the daemon is already executing (based on $PIDFILE), don't re-execute it. 19# 20# To try to minimize the likelihood that the processid stored in the PID file corresponds 21# to an unrelated process (common with startup scripts), we'll clear the contents of the 22# PID file when we kill the daemon using this script. When starting or stopping, when we find a pid in that file, 23# we'll both check that a process with that pid exists, and that the commandname for the process 24# looks like the one we're interested in before we treat the pid value as valid. 25# 26# When stopping, we kill the pid specified in $PIDFILE, if $PIDFILE exists and 27# contains a value that is for a running process whose commandname looks like 28# the one we're interested in. Regardless of how that goes, we'll also 29# kill the service contract (assuming a contract_id is given); that will help 30# us kill the daemon in those cases where the pidfile and the daemon have 31# gotten out-of-sync, as well as ensure all children of the daemon are killed. 32 33 34. /lib/svc/share/smf_include.sh 35 36PATH=/usr/bin:/bin 37 38SERVERROOT=/usr/local/sbin 39 40PROGNAME=dhcp_probe 41 42# If PIDFILE exists and refers to a running process, 43# and that process's command string contains PS_SEARCH, 44# we'll assume this program instance is already running. 45PS_SEARCH=$PROGNAME 46 47EXECUTABLE=$SERVERROOT/$PROGNAME 48 49# Working directory before starting daemon. 50CWD=/tmp 51 52# Directory in which to write the pidfile 53PIDFILEDIR=/var/run 54 55# Directory in which to find the config file 56CONFIGFILEDIR=/etc 57 58# Signal to kill daemon gracefully. 59SIGNAL=TERM 60 61# This will be set via cmdline option '-i interface' 62INTERFACE= 63 64# This may be overridden via cmdline option '-Q vlan_id' 65VLAN_OPT= 66 67# Directory in which to write the capture files 68CAPTUREDIR=/var/local/logs 69 70# Number of capture files to retain (when rotating these files) 71CAPTUREFILES_MAX=20 72 73# Absolute path of the rotate_logs executable. 74# Used when starting service iff '-r' option specified. 75ROTATE_LOGS_EXEC=/usr/local/etc/rotate_logs 76 77# Debug option to pass to dhcp_probe. 78# Set to empty string to disable. 79# May be overridden via '-d debuglevel'. 80DEBUG_OPT="-d 1" 81 82cd $CWD 83 84while [ $# -gt 0 ] 85do 86 case "$1" in 87 88 '-d') 89 # The debuglevel is supposed to be the token after '-d'. 90 # Overrride default DEBUG constant. 91 shift 92 DEBUG_OPT="-d $1" 93 ;; 94 95 '-i') 96 # The interface name is supposed to be the token after '-i'. 97 shift 98 INTERFACE="$1" 99 ;; 100 101 '-Q') 102 # The vlan_id is supposed to be the token after '-Q'. 103 shift 104 if [ "$1" = "none" ]; then 105 # The token "none" is special, indicating that no -Q option should be passed. 106 # It's a kludge to allow our caller to always pass a '-Q value' option, 107 # for those callers (like SMF) which make it hard to pass *optional* options which take values. 108 : 109 else 110 VLAN_OPT="-Q $1" 111 fi 112 ;; 113 114 '-r') 115 rotate_capturefile=1 116 ;; 117 118 '-v') 119 verbose=1 120 ;; 121 122 'start') 123 # The interface must have been specified before the 'start' argument. 124 if [ -z "$INTERFACE" ]; then 125 echo "$0: interface not specified, cannot start $PROGNAME" 2>&1 | smf_console 126 exit $SMF_EXIT_ERR_FATAL 127 fi 128 129 # Some values we could not determine until the INTERFACE was set. 130 131 PIDFILE=$PIDFILEDIR/$PROGNAME.$INTERFACE.pid 132 133 CONFIGFILE=$CONFIGFILEDIR/$PROGNAME.$INTERFACE.cf 134 135 # Capture file name (without the directory name) 136 CAPTUREFILENAME=$PROGNAME.$INTERFACE.capture 137 138 # Absolute capture file name 139 CAPTUREFILE=$CAPTUREDIR/$CAPTUREFILENAME 140 141 STARTCOMMAND="$EXECUTABLE $DEBUG_OPT -c $CONFIGFILE -o $CAPTUREFILE -p $PIDFILE $VLAN_OPT $INTERFACE" 142 143 echo "$0: starting $PROGNAME instance on interface $INTERFACE ..." 2>&1 | smf_console 144 145 if [ ! -f $EXECUTABLE ]; then 146 echo "$0: executable $EXECUTABLE does not exist, cannot start $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 147 exit $SMF_EXIT_ERR_FATAL 148 fi 149 150 if [ ! -f $CONFIGFILE ]; then 151 echo "$0: configuration file $CONFIGFILE does not exist, cannot start $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 152 exit $SMF_EXIT_ERR_CONFIG 153 fi 154 155 # If we find the daemon already running, exit. Else fall through to the $STARTCOMMAND 156 if [ -f $PIDFILE ]; then 157 pid=`/usr/bin/cat $PIDFILE` 158 if [ -n "$pid" ]; then 159 if kill -0 "$pid" > /dev/null 2>&1 ; then 160 # there is a process with that pid, but is it the right one? 161 /usr/bin/ps -f -p $pid | /usr/bin/tail -1 | /usr/bin/grep $PS_SEARCH > /dev/null 2>&1 162 if [ $? -eq 0 ] ; then 163 echo "$0: $PIDFILE=$pid processid exists with reasonable name, assuming $PROGNAME instance on interface $INTERFACE is already running" 2>&1 | smf_console 164 exit $SMF_EXIT_OK 165 else 166 # that process is something else, so we can assume ours isn't already running 167 # Clearing our pidfile is just good housekeeping, not required 168 /usr/bin/cp /dev/null $PIDFILE 169 fi 170 fi # else no process running with that pid, so we assume it's not already running 171 fi # else pidfile doesn't contain a number, so we assume it's not already running 172 fi # else no pidfile, so we assume it's not already running 173 174 # Success! It really looks like the daemon isn't already running, so start it 175 176 ### 177 # This is specific to dhcp_probe 178 # 179 # As each time dhcp_probe starts, it overwrites the capture file. 180 # If you want to preserve the previous capture file(s), rotate those file(s) before starting dhcp_probe. 181 if [ -n "$rotate_capturefile" ] ; then 182 # Note that we could not determine some of these args until after $INTERFACE was set. 183 $ROTATE_LOGS_EXEC -logdir="$CAPTUREDIR" -logname="$CAPTUREFILENAME" -max="-$CAPTUREFILES_MAX" 184 fi 185 # 186 #### 187 188 $STARTCOMMAND 189 echo "done starting $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 190 exit $SMF_EXIT_OK 191 192 193 ;; 194 195 196 197 'stop') 198 199 if [ -z "$INTERFACE" ]; then 200 echo "$0: interface not specified, cannot stop $PROGNAME" 2>&1 | smf_console 201 exit $SMF_EXIT_ERR_FATAL 202 203 # XXX Does Solaris ever call the stop method with just the contract_id (lacking the interface name)? 204 # If so, then we should allow the method to run even without an interface name. 205 # (We really want the interface name as it allows us to find the PIDFILE.) 206 fi 207 208 # We could not determine the PIDFILE until the INTERFACE was set. 209 PIDFILE=$PIDFILEDIR/$PROGNAME.$INTERFACE.pid 210 211 echo "$0: stopping $PROGNAME instance on interface $INTERFACE ..." 2>&1 | smf_console 212 213 # The service contract_id is supposed to be the token after 'stop'. 214 shift 215 contract_id="$1" 216 217 if [ -f $PIDFILE ] ; then 218 219 pid=`/usr/bin/cat $PIDFILE` 220 if [ -n "$pid" ]; then 221 222 if kill -0 "$pid" > /dev/null 2>&1 ; then 223 # there is a process with that pid, but is it the right one? 224 /usr/bin/ps -f -p $pid | /usr/bin/tail -1 | /usr/bin/grep $PS_SEARCH > /dev/null 2>&1 225 if [ $? -eq 0 ] ; then 226 # Success! The process has reasonable name, go ahead and kill it 227 kill -$SIGNAL $pid 228 229 /usr/bin/cp /dev/null $PIDFILE 230 231 # Kill any processes left in service contract 232 if [ -n "$contract_id" ] ; then 233 smf_kill_contract $contract_id $SIGNAL 1 234 [ $? -ne 0 ] && exit 1 235 fi 236 237 echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 238 exit $SMF_EXIT_OK 239 240 else 241 # The process with that pid does NOT have a reasonable name. 242 if [ -n "$verbose" ]; then 243 echo "$0: $PIDFILE=$pid processid is for different daemon, will NOT kill that pid" 2>&1 | smf_console 244 fi 245 # Clearing our pidfile is just good housekeeping, not required 246 /usr/bin/cp /dev/null $PIDFILE 247 248 # It's not clear why the $PIDFILE doesn't correspond to the correct daemon, but perhaps the service is still running with a different pid. 249 # Kill any processes left in service contract 250 if [ -n "$contract_id" ] ; then 251 smf_kill_contract $contract_id $SIGNAL 1 252 [ $? -ne 0 ] && exit 1 253 fi 254 255 echo "done stopping $PROGNAME" 2>&1 | smf_console 256 exit $SMF_EXIT_OK 257 fi 258 259 else 260 # there is no process with that pid 261 if [ -n "$verbose" ]; then 262 echo "$0: $PIDFILE=$pid processid does not exist" 2>&1 | smf_console 263 fi 264 # Clearing our pidfile is just good housekeeping, not required 265 /usr/bin/cp /dev/null $PIDFILE 266 267 # Perhaps the $PIDFILE was overwritten as a result of some problem, but the service is still running. 268 # Kill any processes left in service contract 269 if [ -n "$contract_id" ] ; then 270 smf_kill_contract $contract_id $SIGNAL 1 271 [ $? -ne 0 ] && exit 1 272 fi 273 274 echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 275 exit $SMF_EXIT_OK 276 fi 277 else 278 if [ -n "$verbose" ]; then 279 echo "$0: pidfile $PIDFILE is empty" 2>&1 | smf_console 280 fi 281 282 # Perhaps the $PIDFILE was emptied as a result of some problem, but the service is still running. 283 # Kill any processes left in service contract 284 if [ -n "$contract_id" ] ; then 285 smf_kill_contract $contract_id $SIGNAL 1 286 [ $? -ne 0 ] && exit 1 287 fi 288 289 echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 290 exit $SMF_EXIT_OK 291 fi 292 293 else 294 if [ -n "$verbose" ]; then 295 echo "$0: pidfile $PIDFILE not found" 2>&1 | smf_console 296 fi 297 298 # Perhaps the $PIDFILE was removed as a result of some problem, but the service is still running. 299 # Kill any processes left in service contract 300 if [ -n "$contract_id" ] ; then 301 smf_kill_contract $contract_id $SIGNAL 1 302 [ $? -ne 0 ] && exit 1 303 fi 304 305 echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console 306 exit $SMF_EXIT_OK 307 fi 308 309 # NOTREACHED 310 ;; 311 312 *) 313 echo "$0: Unrecognized argument: $1" 314 echo "Usage:" 315 echo " $0 [-v] -i interface [-Q vlan_id|none] [-r] [-d debuglevel] start" 316 echo " $0 [-v] -i interface stop contract_id" 317 318 exit $SMF_EXIT_ERR_CONFIG 319 ;; 320 esac 321 322 shift 323 324done 325 326