#!/bin/sh # # /etc/init.d/mdsm # # multiple DSM schedule daemons control # # 2013-08-28 RS # # # history: # 2011-06-15 RS v1.1 initial version, see http://adsm.org/lists/html/ADSM-L/2011-06/msg00143.html # 2011-06-16 RS v1.2 added DSM_CONFIG support # 2013-08-28 RS v1.3 added -c switch, sleep time option, and kids' info # ### BEGIN INIT INFO # Provides: mdsm # Required-Start: $network # Required-Stop: $network # Default-Start: 3 5 # Default-Stop: 0 1 2 6 # Description: manage multiple DSM client schedule daemons ### END INIT INFO ## pre # this progname=`basename $0` sysconfig=/etc/sysconfig/$progname # usage usage() { echo "error: $@ usage: $progname [-v|+v] [-c] [] [-- ] manage one ore more DSM schedule daemons where is one of start, stop, restart, or status, or a comma or space separated list thereof, and another list of servernames, i.e. server stanza names from dsm.sys; with no given a default is taken from a variable named \"mdsm_servernames\" to be set in the file \"$sysconfig\"; there, additional command line options my be specified by setting a variable named \"mdsm_schedoptions\", extending given after \"--\" on the command line \"-v\" and \"+v\" may be used to be more or less verbose, where appropriate option \"-c\" will remove error, schedule, and prune logs found in \$DSM_LOG before a start resp. after a stop action examples: $ $0 status $ $0 start,status foo $ $0 stop foo,bar $ $0 status "foo bar" -v " >&2 exit 254 } # some functions echo_out () { echo "$progname: $action: $@" >&1 } echo_err () { echo "$progname: $action error: $@" >&2 } fatal () { echo "$progname: error: $@ - aborting" >&2 exit 255 } spaced_list () { echo "$*" | sed -e 's/, */ /g' } ## options # pre-set ptions opt_actions="" opt_servernames="" opt_schedoptions="" opt_v=1 opt_f=0 opt_c=0 opt_wait=1 # parse command line options while [ ! -z "$1" ] do case "$1" in -h | -help ) usage "help wanted" ;; -v | -f | -c ) id=opt_`echo X$1 | sed 's/^X-//'` eval val=\$$id val=`expr $val + 1` eval $id=$val ;; +v ) id=opt_`echo X$1 | sed 's/^X+//'` eval val=\$$id [ $val -gt 0 ] && val=`expr $val - 1` eval $id=$val ;; -wait ) [ -z "$2" ] && usage "missing argument for option $1" id=opt_`echo X$1 | sed 's/^X\-//'` val="$2" eval $id=$val shift ;; -- ) shift opt_schedoptions="$@" break ;; -* | +* ) usage "unexpected option: $1" ;; *start* | *stop* | *restart* | *status* ) [ -z "$opt_actions" ] || usage "unexpected action: $1" opt_actions=$1 ;; * ) opt_servernames="$opt_servernames $1" ;; esac shift done # check command line options [ -z "$opt_actions" ] && usage "missing action(s)" actions=`spaced_list $opt_actions` for action in $actions do case "$action" in start | stop | restart | status ) ;; * ) usage "unsupported action: $action" ;; esac done # read in sysconfig type options [ -r $sysconfig ] && . $sysconfig [ -z "$opt_servernames" ] || opt_servernames=`spaced_list $opt_servernames` [ -z "$mdsm_servernames" ] || mdsm_servernames=`spaced_list $mdsm_servernames` # build final arguments and options [ -z "$opt_servernames" ] || servernames="$opt_servernames" [ -z "$servernames" ] && servernames="$mdsm_servernames" schedoptions="${opt_schedoptions}${mdsm_schedoptions:+ $mdsm_schedoptions}" # optionally check for servernames list membership if [ $opt_f -eq 0 -a ! -z "$opt_servernames" ] then for servername in $servernames do echo $mdsm_servernames | grep -q -v -w $servername && \ echo_err "servername \"$servername\" not in default servernames list (mdsm_servernames)" && \ rc=3 done [ "$rc" = "3" ] && fatal "add option -f to pass" fi # check environment rundir=/var/run [ ! -d $rundir ] && fatal "missing run directory $rundir" logdir=/var/log [ ! -d $logdir ] && fatal "missing log directory $logdir" ## subs pids_check () { ps -p $pids >/dev/null && isrunning=1 || isrunning=0 } daemon_check () { ext=${servername:+"-$servername"} app=${servername:+"_$servername"} srv=${servername:+"-server=$servername"} txt=${servername:+" for servername \"$servername\""} det="scheduler${txt}" pidfile=/var/run/$progname${ext}.pid haspidfile=0 && [ -f $pidfile ] && haspidfile=1 pids="" && [ $haspidfile = 1 ] && pids="`cat $pidfile`" haspids=0 && [ ! -z "$pids" ] && haspids=1 kidinfo= if [ $haspids = 1 -a $opt_v -gt 1 ] then kids=`for p in $pids do ps -Ao pid,ppid $p | \ while [ 1 ] do read _pid _ppid || break [ $_ppid = $p ] && echo $_pid done done` kidinfo=${kids:+", kids $kids"} kidinfo=${kids:-", no kids"} fi pidinfo="" && [ $opt_v -gt 0 ] && pidinfo=" (pid ${pids}${kidinfo})" [ $haspidfile = 1 ] && [ $haspids = 0 ] && \ echo_err "found empty pid file of $det" && return 2 isrunning=0 && [ $haspids = 1 ] && pids_check [ $haspids = 1 ] && [ $isrunning = 0 ] && \ echo_err "found died process of $det (had pid $pids)" && \ return 2 } status_daemon () { _rc_=1 dci="" daemon_check if [ $isrunning = 1 ] then if [ $opt_v -gt 2 ] then _pat="DSM_CONFIG=" dsm_config=`ps -ww p $pids e | grep $_pat | sed 's/.*'$_pat'\([^ ]*\).*/\1/'` [ ! -z "$dsm_config" ] && \ envinfo=" [DSM_CONFIG=$dsm_config]" || \ envinfo=" [DSM_CONFIG not set]" fi echo_out "$det is running${pidinfo}${envinfo}" _rc_=0 else if [ $opt_v -gt 1 ] then dsm_config="" get_dsmconfig [ ! -z "$dsm_config" ] && \ envinfo=" [next DSM_CONFIG=$dsm_config]" || \ envinfo=" [next DSM_CONFIG not set]" fi echo_out "$det is not running$envinfo" fi return $_rc_ } get_dsmconfig () { dsmconfig_app=mdsm_dsmconfig${app} eval dsmconfig=\$$dsmconfig_app if [ -z "$dsmconfig" -a ! -z "$mdsm_dsmconfigpattern" ] then eval dsmconfig=`echo $mdsm_dsmconfigpattern | sed 's/%sn/'$servername'/g'` [ $? -ne 0 ] && \ echo_err "could not evaluate pattern '$mdsm_dsmconfigpattern'" && \ return 1 fi if [ -z "$dsmconfig" ] then # nop dsmconfig="" elif [ -f "$dsmconfig" ] then dsm_config=$dsmconfig DSM_CONFIG=$dsm_config export DSM_CONFIG else echo_err "could not find option file $dsmconfig" return 1 fi return 0 } clean_logs () { _rc_=0 if [ $opt_c -gt 0 ] then rm -f $DSM_LOG/dsmerror.log $DSM_LOG/dsmsched.{log,pru} _rc_=$? [ $_rc_ -eq 0 ] && echo_out "removed log files " || \ echo_err "removing log files failed" fi return $_rc_ } start_daemon () { _rc_=1 daemon_check if [ $isrunning = 1 ] then echo_out "$det is already running${pidinfo}" elif get_dsmconfig then clean_logs nohup dsmc schedule $schedoptions $srv >/dev/null 2>&1 & echo $! > $pidfile sleep $opt_wait daemon_check if [ $isrunning = 1 ] then echo_out "started ${det}${pidinfo}" _rc_=0 else echo_err "could not start $det" rm -f $pidfile fi fi return $_rc_ } stop_daemon () { _rc_=1 _det_="" daemon_check if [ $isrunning = 1 ] then kill $pids sleep $opt_wait pids_check if [ $isrunning = 1 ] then _det_="forcibly " kill -9 $pids pids_check [ $isrunning = 1 ] && \ echo_err "could not stop ${det}${pidinfo}" && \ return $_rc_ fi echo_out "${_det_}stopped ${det}${pidinfo}" rm $pidfile && _rc_=0 || \ echo_err "could not delete pid file of ${det}${pidinfo}" clean_logs else echo_out "$det is not running yet" fi return $_rc_ } restart_daemon () { stop_daemon sleep $opt_wait start_daemon } ## main # perform action(s) DSM_LOG=$logdir export DSM_LOG rc=0 _rc=0 # manage (one or more) schedule daemon(s) for servername in ${servernames:-""} do mdsm_servername=$servername for action in $actions do eval ${action}_daemon _rc=$? [ $_rc -ne 0 ] && [ $rc -eq 0 ] && rc=$_rc done done exit $rc