#!/bin/ksh # # $Source: /usr/local/scripts/ntp/RCS/do-rrdntp,v $ # $Revision: 1.2 $ $Date: 2010/01/29 20:00:41 $ # $Author: root $ # # $Log: do-rrdntp,v $ # Revision 1.2 2010/01/29 20:00:41 root # version3 checkpoint (working) # # Revision 1.1 2010/01/28 20:59:19 root # Initial revision # # Revision 1.16 2008/04/16 03:23:31 root # added log level 2 - no truncation # # Revision 1.15 2008/04/11 08:27:18 root # added GNUplot handler for ntp statistics files (loop,peer,sys) # # Revision 1.14 2008/04/09 06:32:42 root # modified to read MOST data from ntp-client file - instaed of splitting # client data across 2 files # # Revision 1.13 2008/03/21 00:52:18 root # added SSRVS group to hosts - time critical servers (certserver like) # # Revision 1.12 2008/03/20 02:42:34 root # moved logfile to different directory # # Revision 1.11 2008/03/20 01:10:03 root # added fixed revision to debug preamble... don't forget to update # # Revision 1.10 2008/03/20 01:07:38 root # added command/configuration file processing # added -r (norun) flag # added pre configuration read io redirection # added date preable to logfile # # Revision 1.9 2008/03/19 06:52:47 root # fixed RRDDSVER bug (not resetting in loop) # # Revision 1.8 2008/03/19 06:43:49 root # added dataset version to graph titles # # Revision 1.7 2008/03/19 06:02:21 root # added debug trace for combined charts # # Revision 1.6 2008/03/19 05:41:48 root # added io redirection for debug and logfiles # added cmdline agrs for debug and logging # added rrd data set version handling - verify new format (values) before # graphing or accessing) them. (allows for transition to updated data sets # # Revision 1.5 2008/03/18 03:27:22 root # moved server defs to top # added color defs (for combined charts) # # Revision 1.4 2008/03/17 23:15:00 root # more motech merges - moved to ksh, added combined graphs, trending # # # Revision History: MGO 11-Mar-2008 Modified graphs to correct # auto-scale diffs from v1.0 # to v1.2. # (alt-y-grid, slope-mode, # x-grid... ) # MGO 15-Mar-2008 Merged changes from motech # MGO 18-Mar-2008 Added command line args for # debug level and chart only. # MGO 10-Jan-2010 Mods to support apache in # Sol10 ZONE! # MGO 11-Jan-2010 Seperated raw and mode6 data # collection - raw is BIG scp... # MGO 21-Jan-2010 Mods for bit masks # MGO 28-Jan-2010 Mods for rrdtool timeouts, # to kill runaway rrd graphs. # MGO 29-Jan-2010 Added SYSTEM stats. # # rebuilt for the ntpq stats 27 mar 2006 gnu@wraith.sf.ca.us # public domain # hardcoded config file paths - typically in same dir as exec (myself) execFile="cmds.inc" # command locations confFile="ntpstats.conf" # system configurations confDir="" # debug level (normally 0, but could be 4-6 for extreme output) # NOTE: normally command output > /dev/null, unless debug>=5 debug=5 # operational stuff # you MUST set this to a zon-zero value when called via cron! - # or you'll be barraged by email every 5 minutes. # (Note: -1=>/dev/null, 0=>stdout, 1=>trucateLog, 2=>append to log) log=1 # send to log doall=0 # set... do BOTH stats and mode6 nocollect=0 # don't collect (just draw charts) noplot=0 # don't plot (just collect) norun=0 # don't collect OR chart doicmp=1 # Ping the host before transfer.... startdelay=0 # allow sleep to offset exact cron start # this is use to delay processing by a # few seconds to allow ntp stats on the 00 ntpmode6=1 # do mode6 by default ntpqtimeout=5000 # mode6 query timeout (sets do-ntp-rrd.. -t) do_ntp_rrdstats="" # set flags accordingly # some process variables alarmpid=0 estatus=0 procid=0 wdtimer=0 # rrdtool watchdog timeout # ensure bg processes are NOT auto-niced. set +o bgnice ################################################################################ ################################################################################ ## ## NO USER SERVICABLE PART BELOW ## # # THE help function.... # usage() { print "usage: ${myname} [-acilnpr] [-d] [-s] [-w] [-t]" print " -a collect ALL data" print " -c collect NO data (useful in concert with the -p option)" print " -i disable icmp (ping) check" print " -l enable logging (at level 1)" print " -n collect NTP mode 6 data (via 'ntpq -c rv HOST')" print " -p disable plot generation (rrdtool graph)" print " -r no run (also sets -c and -r)" print " -d<1-5> sets debug level (w/o argument disables debug)" print " -s delay actual start for N seconds (useful in cron)" print " -w rrdtool watchdig timeout (kill rrdtool after n seconds)" print " -t ntpq query timeout (mSec) - default is 5000" exit 0 } # signal handler to trap ALRM # pass debug state and procid to kill timeout_handler () { typeset _debug=${1} typeset _procid=${2} [[ ${_debug} -ge 0 ]] && print \ "${myname}/${mypid} ERR: PID ${procid} killed after ${wdtimer}" # Kill the process which didn't complete as expected # If $procid isn't set, we got called too soon. [[ "X${procid}" != "X" && ${procid} -ne 0 ]] && ${_KILL} -TERM ${procid} # update wdtimeouts #(( wdtimeouts += 1 )) # Set an exit status to be returned to indicate timeout estatus=127 } # watchdog process # zero procid and estatus... # - set procid from spawned proc # - ALARM handler sets estatus on timeout # set watchdog IRQ for $1 seconds start_watchdog () { typeset _start=$( ${_DATE} '+%T' ) [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: Starting watchdog ${1}s timer (@ ${_start})" >&4 alarmpid=0 estatus=0 procid=0 [[ "Z${1}" = "Z" || ${1} -eq 0 ]] && return 0 #trap timeout_handler ALRM ( ${_SLEEP} ${1} ${_KILL} -ALRM ${mypid} >&5 2>&5 ) & alarmpid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: Watchdog PID ${alarmpid}" >&4 return ${alarmpid} } # handle watched process and ALL returns # $1 procid to wait on # $2 alarm process - from start_watchdog() # SINCE traps are local to functions - we set the trap HERE! return_handler () { typeset _err if [[ "Z${1}" = "Z" || "$Z{2}" = "Z" ]] ; then [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: return_handler - bad options (killing watchdog)" >&4 [[ ${alarmpid} -ne 0 ]] && \ ${_KILL} -TERM ${alarmpid} >&5 2>&5 trap - ALRM return 0 fi [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - PID=${1} ALRM=${2} (procid=${procid} alrmpid=${alarmpid})" >&4 if [[ ${1} -ne 0 ]] ; then trap "timeout_handler ${debug}" ALRM [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - waiting for PID ${1}" >&4 wait ${1} _err=$? pstatus=$! typeset _stop=$( ${_DATE} '+%T' ) [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - wait returns $_err" >&4 #if [[ ${estatus} -ne 0 ]] ; then # (( wdtimeouts += 1 )) # [[ ${debug} -ge 2 ]] && print \ # "${myname}/${mypid} DBG: return_handler - PID ${1} timeout" >&4 #fi # just in case (bug in timeout handler - or KSH...) # is procid (rrdtool) still running? ${_PS} -p ${1} >&5 2>&5 _err=$? if [[ $_err -eq 0 ]] ; then [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - KILLing PID ${1}" >&4 ${_KILL} -TERM ${1} >&5 2>&5 #(( wdtimeouts += 1 )) fi fi [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - sending ${2} SIGTERM" >&4 ${_KILL} -TERM ${2} >&5 2>&5 trap - ALRM [[ ${estatus} -ne 0 ]] && pstatus=${estatus} [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: return_handler - return ${pstatus} (@ ${_stop})" >&4 return ${pstatus} } myname=${0##*/} mydir=${0%/*} # dirname [[ ${mydir} == ${myname} ]] && mydir="." # dirname puts . for no dir mypid=$$ myargs="$0 $1 $2 $3 $4 $5 $6 $7 ..." # capture SOME args... #------------------------------------------------------------------------------- # get options and set params... OPTIONS="achilnprd:s:w:t:" while getopts ${OPTIONS} FLAGS do case ${FLAGS} in 'a') doall=1 ;; 'c') nocollect=1 ;; 'h') usage ;; 'i') doicmp=0 ;; 'l') log=1 ;; 'n') ntpmode6=0 ;; 'p') noplot=1 ;; 'r') norun=1 nocollect=1 noplot=1 ;; 'd') if [[ "X${OPTARG}" != "X" ]] ; then debug=${OPTARG} else debug=0 fi ;; 's') if [[ "X${OPTARG}" != "X" ]] ; then startdelay=${OPTARG} else startdelay=0 fi ;; 't') ntpqtimeout=${OPTARG} [[ ${ntpqtimeout} -lt 250 ]] && ntpqtimeout=5000 ;; 'w') if [[ "X${OPTARG}" != "X" ]] ; then wdtimer=${OPTARG} else wdtimer=0 fi ;; '?') print "${myname}: unknown option (possible ${OPTIONS})" exit 2 ;; '*') ;; esac done shfcnt=$(( OPTIND - 1 )) shift ${shfcnt} #------------------------------------------------------------------------------- # get the configuration stuff # temp stdio redirect on debug level (!=0 > /dev/null) - no logging # availible, coz we've NOT yet read the configurations. if [[ ${debug} -ge 2 && ${log} -eq 0 ]] ; then exec 3>&1 else exec 3>/dev/null fi if [[ "${mydir}" != "." ]] ; then if [[ ! -f /${mydir}/${myname} ]] ; then execpath=${PWD} # shell pwd execpath="${execpath}/${mydir}" [[ ${debug} -ge 4 ]] && print \ "${myname} DBG: searching ${execpath} (for ${myname})" >&3 if [[ -f "${execpath}/${myname}" ]] ; then confDir=${execpath} [[ ${debug} -ge 3 ]] && print \ "${myname} DBG: Set confDir to ${execPath} (via cmdline/cwd)" >&3 else [[ ${debug} -ge 0 ]] && print \ "${myname} ERR: Something is pathalogic - can't find myself" exit 2 fi else execPath=${mydir} [[ ${debug} -ge 2 ]] && print \ "${myname} DBG: Set execPath to ${execPath} (via cmdline)" >&3 fi else [[ ${debug} -ge 2 ]] && print "Searching for exec dir" >&3 if [[ -f ${myname} ]] ; then execPath=${PWD} # shell pwd [[ ${debug} -ge 2 ]] && print \ "Set execPath to current dir ${execPath} (via pwd)" >&3 else execpath=$( which ${myname} ) #${_ECHO} ${execpath} | ${_GREP} "no ${myname} in" if [[ ${execPath%*no ${myname} in*} == ${execPath} ]] ; then # which found something in the path [[ ${execPath} == ${execPath%%/*} ]] && execPath="." execPath=${execPath%/*} # dirname [[ ${debug} -ge 2 ]] && print \ "${myname} DBG: Setting execPath from search path ${execPath}" >&3 else [[ ${debug} -ge 0 ]] && print \ "${myname} ERR: Unable to determine execPath - exiting" exit 2 fi fi fi # now we have execPath - look for includes. They be here or ../data if [[ ! -f ${execPath}/${execFile} ]] ; then if [[ ! -f ${confDir}/${execFile} ]] ; then [[ ${debug} -ge 0 ]] && print \ "${myname} ERR: Unable to find ${execFile} - exiting" exit 2 else [[ ${debug} -ge 4 ]] && print \ "${myname} DBG: Reading ${execFile} from ../confDir" >&3 . ${confDir}/${execFile} fi else [[ ${debug} -ge 4 ]] && print \ "${myname} DBG: Reading ${execFile} from execPath" >&3 . ${execPath}/${execFile} fi # now look for configuration file - they be in the confDir if [[ ! -f ${execPath}/${confFile} ]] ; then if [[ ! -f ${confDir}/${confFile} ]] ; then [[ ${debug} -ge 0 ]] && print \ "${myname} ERR: Unable to find ${confFile} - exiting" exit 2 else [[ ${debug} -ge 4 ]] && print \ "${myname} DBG: Reading ${confFile} from ../confDir" >&3 . ${confDir}/${confFile} fi else [[ ${debug} -ge 4 ]] && print \ "${myname} DBG: Reading ${confFile} from execPath" >&3 . ${execPath}/${confFile} fi # make some operational dirs - just in case [[ ! -d ${DBDIR} ]] && ${_MKDIR} -p ${DBDIR} [[ ! -d ${STATDIR} ]] && ${_MKDIR} -p ${STATDIR} # setup loging to file (or stdout) depending on -l # NOTE: all output uses FD4.... we just set FD4 as needed # NOTE on file truncation: the exec redirection truncates the file (and no # amount of gt magic stops it), BUT, using 'set -C' before the exec # does prevent file truncation. (the wonders of ksh...) _LOGEXT="_m6" [[ ${ntpmode6} -ne 1 ]] && _LOGEXT="_stats" if [[ ${log} -ge 1 ]] ; then LOGFILE=${DATADIR}/${myname}${LOGEXT}.log [[ ! -f ${LOGFILE} ]] && ${_TOUCH} ${LOGFILE} >/dev/null 2>&1 if [[ ${log} -ge 2 ]] ; then exec 4>>${LOGFILE} else exec 4>${LOGFILE} fi else if [[ ${log} -lt 0 ]] ; then exec 4>/dev/null else exec 4>&1 fi fi # setup stdio redirect on debug level (<5 > /dev/null) # NOTE: all command output uses FD5... set according to need if [[ ${debug} -ge 5 ]] ; then exec 5>&4 else exec 5>/dev/null fi if [[ ${debug} -ge 1 && ${log} -ge 1 ]] ; then print "" >&4 print \ "=====================================================================" >&4 ${_DATE} '+%D %T' >&4 fi [[ ${debug} -ge 2 ]] && print "From command line: ${myname} ${mydir}" >&4 [[ ${debug} -ge 3 ]] && print "\targs: ${myargs} (shift ${shfcnt})" >&4 # # Start of processing # if [[ ${debug} -ge 1 ]] ; then print "${myname}/${mypid} DBG: version 1.19" >&4 [[ ${startdelay} -gt 0 ]] && print \ "${myname}/${mypid} DBG: startdelay set to ${startdelay} seconds" >&4 [[ ${nocollect} -ne 0 ]] && print \ "${myname}/${mypid} DBG: nocollect set - graph only" >&4 [[ ${doicmp} -eq 0 ]] && print \ "${myname}/${mypid} DBG: icmp disabled - no ping check" >&4 [[ ${norun} -ne 0 ]] && print \ "${myname}/${mypid} DBG: norun set - no graph either" >&4 [[ ${ntpmode6} -eq 0 ]] && print \ "${myname}/${mypid} DBG: ntpmode6 un-set - graph RefClk data (vs NTP)" >&4 print "${myname}/${mypid} DBG: ntpqtimeout ${ntpqtimeout}" >&4 [[ ${noplot} -ne 0 ]] && print \ "${myname}/${mypid} DBG: noplot set - collect only" >&4 print "${myname}/${mypid} DBG: RRDDSCUR version ${RRDDSCUR}" >&4 fi if [[ ${debug} -ge 2 ]] ; then print "${myname}/${mypid} DBG: Client File='${CLNTFILE}'" >&4 fi if [[ ${debug} -ge 3 ]] ; then print "${myname}/${mypid} DBG: SCRIPT_BIN = ${SCRIPT_BIN}" >&4 print "${myname}/${mypid} DBG: DATADIR = ${DATADIR}" >&4 print "${myname}/${mypid} DBG: CONFDIR = ${CONFDIR}" >&4 print "${myname}/${mypid} DBG: CLNTFILE = ${CLNTFILE}" >&4 print "${myname}/${mypid} DBG: DBDIR = ${DBDIR}" >&4 print "${myname}/${mypid} DBG: WEBOUT = ${WEBOUT}" >&4 print "${myname}/${mypid} DBG: TMPDIR = ${TMPDIR}" >&4 fi if [[ ${startdelay} -gt 0 ]] ; then [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: Delaying startup by ${startdelay} seconds" >&4 ${_SLEEP} ${startdelay} fi if [[ ${wdtimer} -gt 0 ]] ; then [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: rrdtool watchdog timer is ${wdtimer} seconds" >&4 fi if [[ ! -f ${SystemStats} ]] ; then ${_RRDTOOL} create ${SystemStats} \ DS:user:ABSOLUTE:1200:0:65536 \ DS:system:ABSOLUTE:1200:0:U \ DS:readerrs:GAUGE:1200:0:U \ DS:rrderr:GAUGE:1200:0:U \ DS:rrdwd:GAUGE:1200:0:U \ DS:gnuperr:GAUGE:1200:0:U \ DS:gnupwd:GAUGE:1200:0:U \ RRA:AVERAGE:0.5:1:312 \ >&5 2>&5 fi # zero some runtime stat counters wdtimeouts=0 sysuser=$(( 1 << DO_RRDNTP )) sysid=0 sysreer=0 rrderr=0 rrdwdto=0 gnuerr=0 gnuwdto=0 # temp counters - until we get rrd setup if [[ ! -f ${DBDIR}/WDTimeouts ]]; then ${_ECHO} 0 > ${DBDIR}/WDTimeouts fi wdtimeouts=$( ${_CAT} ${DBDIR}/WDTimeouts ) RRDDSVER=1 # RRD data file version _PING=${SCRIPT_BIN}/my_ping # use local OS independent ping cocount=0 # Combined charts array index pdate=$( ${_DATE} '+%d-%b' ) wdate=$( ${_DATE} '+%b-%U' ) [[ ${ntpmode6} -eq 0 ]] && do_ntp_rrdstats="-n" # set ntpq timeout.... [[ ${ntpqtimeout} -ne 5000 ]] && \ do_ntp_rrdstats="${do_ntp_rrdstats} -t ${ntpqtimeout}" [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: Starting proc loop:\n" >&4 exec 7< ${CLNTFILE} while read -u7 HLine do ConfFmt=1 # conf entry format # grok config line [[ ${debug} -ge 5 ]] && print \ " ${myname}/${mypid} DBG: Line ${HLine}" >&4 Group=${HLine%%;*} # Group # comment [[ "X${Group%%#*}" == "X" ]] && continue HLine=${HLine#*;} # next field HOST=${HLine%%;*} # host HLine=${HLine#*;} # next field IPADDR=${HLine%%;*} # IP address HLine=${HLine#*;} # next field Enabled=${HLine%%;*} # Entry active (or not) HLine=${HLine#*;} # next field Display=${HLine%%;*} # display (or not) HLine=${HLine#*;} # next field HLine=${HLine#*;} # skip OS HLine=${HLine#*;} # skip CPU HLine=${HLine#*;} # skip Reference HLine=${HLine#*;} # skip Notes Color=${HLine%%;*} # MultiPlot color HLine=${HLine#*;} # next field _tmpF=${HLine%%;*} # Read to determine record format [[ "${_tmpF##0x}" != "${_tmpF}" ]] && \ ConfFmt=2 # Next field contain 0x ==> fmt==2 [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: $HOST record format => ${ConfFmt}." >&4 # if [[ ${ConfFmt} -lt 2 ]] ; then # BitNum=0 # NTPBitMask=0 # BitCnt=(( ${#V1ATTRIB[*]} + ${#V2ATTRIB[*]} )) # while (( BitNum < BitCnt )); do # Bits=${HLine%%;*} # [[ ${debug} -ge 4 ]] && print \ # "${myname}/${mypid} DBG: &4 # [[ ${Bits} -ne 0 ]] && NTPBitMask=(( NTPBitMask + (1<&4 # else # NTPBitMask=${_tmpF} # [[ ${debug} -ge 3 ]] && print \ # "${myname}/${mypid} DBG: >V3 bitmask is ${NTPBitMask}" >&4 # fi # HLine=${HLine#*;} # skip N/A # get stats if [[ "${Enabled}" != "1" ]] ;then [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: $HOST (IP=${IPADDR}) Disabled - skipping." >&4 continue fi # the combined entry - this ONLY works if ~Combined is the LAST! # Carry the config values into the combined chart section (the end) if [[ ${HOST%%~*} != ${HOST} ]] ; then [[ "${HOST}" != "~Combined" ]] && continue [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: ~Combined - better be last entry!" >&4 break fi [[ "${IPADDR}" == "-" ]] && IPADDR=${HOST} [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: doing host $HOST (IP=${IPADDR}, Disp=$Display, Color=$Color)" >&4 if [[ ${doicmp} -gt 0 ]] ; then ${_PING} ${IPADDR} 1 >&5 2>&5 err=$? [[ $err -ne 0 ]] && continue [[ ${debug} -ge 3 ]] && print "${myname}/${mypid} DBG: ping ${IPADDR} OKAY" >&4 fi [[ ${debug} -ge 3 && ${nocollect} -eq 0 ]] && print \ "${myname}/${mypid} DBG: Call ${SCRIPT_BIN}/do-ntp-rrdstats ${do_ntp_rrdstats} ${HOST} ${IPADDR}" >&4 [[ nocollect -eq 0 ]] && \ ${SCRIPT_BIN}/do-ntp-rrdstats ${do_ntp_rrdstats} ${HOST} ${IPADDR} # mk dir iff not found [[ ! -d ${WEBOUT}/${HOST} ]] && \ ${_MKDIR} ${WEBOUT}/${HOST} >&5 2>&5 # is the RRD there? - WTF! if [[ ! -f ${DBDIR}/${HOST}.rrd ]] ; then [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} ERR: ${DBDIR}/${HOST}.rrd NOT found - WTF!" >&4 continue fi # determine RRD DS version - and act accordingly... # V2 includes precision,delay,dispersion,stratum,peer RRDDSVER=1 # reset RRD data file version ${_RRDTOOL} info ${DBDIR}/${HOST}.rrd | \ ${_GREP} "precision" >&5 2>&5 err=$? [[ $err -eq 0 ]] && RRDDSVER=2 ${_RRDTOOL} info ${DBDIR}/${HOST}.rrd | \ ${_GREP} "associd" >&5 2>&5 err=$? [[ ${err} -eq 0 ]] && RRDDSVER=3 [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: RRD DS Version = ${RRDDSVER}" >&4 set -A DATTRIB ${V1ATTRIB[*]} [[ ${RRDDSVER} -ge 2 ]] && set +A DATTRIB ${DATTRIB[*]} ${V2ATTRIB[*]} [[ ${RRDDSVER} -ge 3 ]] && set +A DATTRIB ${DATTRIB[*]} ${V3ATTRIB[*]} aCount=${#DATTRIB[*]} [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: collecting V${RRDDSVER}: ${#DATTRIB[*]}=>'${DATTRIB[*]}'" >&4 # dailies count=0 # noplot - set count > aCount [[ ${noplot} -ge 1 ]] && count=${aCount} while (( count < aCount )) do ATTRIB=${DATTRIB[$count]} [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: generating ${ATTRIB} graph" >&4 # setup some special labels/scaling/etc.... LABEL=${ATTRIB} VALUE=${ATTRIB} AUTO_SCALE="" UNIT_EXP="" TUNITS="" SCALE=1 RAWFILEY=0 # gnuplot file Y value RAWFILEXMAX="" RAWFILE="" case "${ATTRIB}" in "offset") VALUE=s${ATTRIB} # scaled by $SCALE TUNITS="(Sec)" SCALE=1000 # value already mSec RAWFILEY=3 # gnuplot file Y value RAWFILEXMAX=loopTOD RAWFILE="loopstats" ;; "jitter") VALUE=s${ATTRIB} # scaled by $SCALE TUNITS="(Sec)" SCALE=1000 # value already mSec RAWFILEY=5 # gnuplot file Y value RAWFILEXMAX=loopTOD RAWFILE="loopstats" ;; "noise") ;; "stability") TUNITS="(ppm)" ;; "frequency") TUNITS="(ppm)" AUTO_SCALE="--alt-autoscale" RAWFILEY=4 # gnuplot file Y value RAWFILEXMAX=loopTOD RAWFILE="loopstats" ;; "precision") ;; "delay") ;; "dispersion") VALUE=s${ATTRIB} # scaled by $SCALE TUNITS="(Sec)" SCALE=1000 # value already mSec ;; "stratum") ;; "peer") ;; "associd") ;; "status") ;; "poll") ;; "tai") ;; "state") ;; "leap") ;; "refid") ;; "reftime") ;; "clock") ;; *) ;; esac # do rrd type graphs.... if [[ ${ntpmode6} -eq 1 ]] ; then [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: ${HOST} Plotting NTP mode6 data." >&4 # Daily - by 5 min interval start_watchdog ${wdtimer} ${_RRDTOOL} graph \ -W "${HOST}_${ATTRIB}" \ --imgformat PNG ${WEBOUT}/${HOST}/${ATTRIB}.png \ --title "${HOST} (V${RRDDSVER}) - ${pdate}" \ --slope-mode \ --x-grid HOUR:1:HOUR:6:HOUR:6:0:%R \ --alt-y-grid \ ${AUTO_SCALE} \ ${UNIT_EXP} \ --start -93600 \ DEF:${ATTRIB}=${DBDIR}/${HOST}.rrd:${ATTRIB}:AVERAGE \ CDEF:s${ATTRIB}=${ATTRIB},${SCALE},/ \ LINE0.75:${VALUE}#0000FF:"\"${LABEL} ${TUNITS}\"" \ GPRINT:${VALUE}:LAST:%le \ >&5 2>&5 & procid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: spawned Daily-${ATTRIB} ${_RRDTOOL} PID ${procid}" >&4 return_handler ${procid} ${alarmpid} # weeklies start_watchdog ${wdtimer} ${_RRDTOOL} graph \ -W "${HOST}_W${ATTRIB}" \ --imgformat PNG ${WEBOUT}/${HOST}/week-${ATTRIB}.png \ --title "${HOST} (V${RRDDSVER}) - ${wdate}" \ --slope-mode \ --x-grid HOUR:4:DAY:1:DAY:1:432000:%a \ --alt-y-grid \ ${AUTO_SCALE} \ ${UNIT_EXP} \ --start -691200 \ DEF:${ATTRIB}=${DBDIR}/${HOST}.rrd:${ATTRIB}:AVERAGE \ CDEF:s${ATTRIB}=${ATTRIB},${SCALE},/ \ LINE0.75:${VALUE}#0000FF:"\"${LABEL} ${TUNITS}\"" \ GPRINT:${VALUE}:LAST:%le \ >&5 2>&5 & procid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: spawned Weekly-${ATTRIB} ${_RRDTOOL} PID ${procid}" >&4 return_handler ${procid} ${alarmpid} else # # Do the gnuplot of raw data - RAWFILEXMAX is also used as a # lockfile, during the file scp update process it is removed.... # if [[ "X${RAWFILEXMAX}" != "X" ]] ; then if [[ -f ${STATDIR}/${RAWFILEXMAX}.${HOST} ]] ; then # compute X offset (based on max value from loopTOD.HOST file) # a weeks worth XEND=`${_CAT} ${STATDIR}/${RAWFILEXMAX}.${HOST}` 2>&5 if [[ ${XEND} -gt 0 ]] ; then (( XSTART = XEND - 86400 )) [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: ${HOST} GNUplot x-axis ${XSTART} to ${XEND}" >&4 # reset for hour graph XSCALEDEND=0 XSCALEDSTART=-24 # 24 hours prior XSCALEDWEEKSTART=-8 # 8 days prior tdate=$( ${_DATE} '+%d-%b' ) ${_CAT} <<-GNUFILE > ${STATDIR}/${ATTRIB}-${HOST}.gnu # # This file will create the daily and weekly plots for # the ${ATTRIB} from the ${RAWFILE} dataset for ${HOST}. # # output to file set term png set output "${WEBOUT}/${HOST}/${ATTRIB}-raw.png" # setup x axis (-24 hours to NOW) set xrange [${XSCALEDSTART}:${XSCALEDEND}] # tick every 2 hours #set xtics 1, 2 # minor every 30 mins set mxtics 4 set xlabel '${tdate} Hours' # setup y axis set ylabel "${ATTRIB}" set grid xtics ytics plot "${STATDIR}/${RAWFILE}.${HOST}" using ((((\$1*86400)+int(\$2))-int($XEND))/3600):${RAWFILEY} notitle with linespoints # plot for weekly stats set output "${WEBOUT}/${HOST}/week-${ATTRIB}-raw.png" # setup x axis (-8 days to NOW) set xrange [${XSCALEDWEEKSTART}:${XSCALEDEND}] # tick every 1 day #set xtics 1, 1 # minor every 12 hours set mxtics 2 set xlabel '${tdate} Days' plot "${STATDIR}/${RAWFILE}.${HOST}" using ((((\$1*86400)+int(\$2))-int($XEND))/86400):${RAWFILEY} notitle with linespoints GNUFILE if [[ -x ${_GNUPLOT} ]] ; then [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: Calling GNUplot with ${STATDIR}/${ATTRIB}-${HOST}.gnu" >&4 start_watchdog ${wdtimer} ${_GNUPLOT} ${STATDIR}/${ATTRIB}-${HOST}.gnu >&5 2>&5 & procid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: spawned ${_GNUPLOT} PID ${procid}" >&4 return_handler ${procid} ${alarmpid} fi # -x GNUPLOT fi # XEND -gt 0 fi # -f ${STATDIR}/${RAWFILEXMAX}.${HOST} fi # "X${RAWFILEXMAX}" != "X" fi # else ${ntpmode6} -eq 1 (( count += 1 )) done ${_CHMOD} 644 ${WEBOUT}/${HOST}/* >&5 2>&5 # build Combined data - CHOSTS and CCOLOR arrays if [[ "X${Color}" != "X" && ${Color} != "-" ]] ; then [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: Combined host entry $HOST (color $Color)" >&4 CHOSTS[${cocount}]=${HOST} CCOLORS[${cocount}]=$Color (( cocount += 1 )) fi [[ ${debug} -ge 2 ]] && print >&4 done # # Now we do the combined graphs - for a quick comparison of the clocks # [[ ${debug} -ge 1 ]] && print \ "${myname}/${mypid} DBG: Doing Combined charts" >&4 [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: ${cocount} Combined HOSTS to plot" >&4 # mk dir iff not found [[ ! -d ${WEBOUT}/Combined ]] && \ ${_MKDIR} ${WEBOUT}/Combined >&5 2>&5 aCount=${#CATTRIB[*]} count=0 [[ ${noplot} -ge 1 ]] && count=${aCount} while (( count < aCount )) do ATTRIB=${CATTRIB[$count]} RRDDEF="" RRDLINE="" # build data defs dCount=${#CHOSTS[*]} cCount=0 while (( cCount < dCount )) do HOST=${CHOSTS[$cCount]} COLOR=${CCOLORS[$cCount]} # determine RRD DS version - and act accordingly... # V2 includes precision,delay,dispersion,stratum,peer ${_RRDTOOL} info ${DBDIR}/${HOST}.rrd | \ ${_GREP} ${ATTRIB} >&5 2>&5 err=$? if [[ ${err} -eq 0 ]] ; then [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: ${HOST} RRD DS contains ${ATTRIB} value" >&4 RRDDEF="${RRDDEF} DEF:${HOST}=${DBDIR}/${HOST}.rrd:${ATTRIB}:AVERAGE" RRDLINE="${RRDLINE} LINE0.75:${HOST}#${COLOR}:\"${HOST}\"" fi (( cCount += 1 )) done [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: DEF line for rrdgraph: ${RRDDEF}" >&4 [[ ${debug} -ge 4 ]] && print \ "${myname}/${mypid} DBG: LINE line for rrdgraph: ${RRDLINE}" >&4 HEIGHT=200 [[ "${ATTRIB}" == "stratum" ]] && HEIGHT=50 # if we have variables to display, then do the chart.... if [[ "X${RRDDEF}" != "X" ]]; then # Daily - by 5 min interval [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: generating Combined ${ATTRIB} graph" >&4 start_watchdog ${wdtimer} ${_RRDTOOL} graph \ -W "Combined_${ATTRIB}" \ --imgformat PNG ${WEBOUT}/Combined/${ATTRIB}.png \ --height ${HEIGHT} \ --title "${ATTRIB} - ${pdate}" \ --slope-mode \ --x-grid HOUR:1:HOUR:6:HOUR:6:0:%R \ --alt-y-grid \ ${AUTO_SCALE} \ --start -93600 \ ${RRDDEF} \ ${RRDLINE} \ >&5 2>&5 & procid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: spawned Combined-${ATTRIB} ${_RRDTOOL} PID ${procid}" >&4 return_handler ${procid} ${alarmpid} # weeklies [[ ${debug} -ge 2 ]] && print \ "${myname}/${mypid} DBG: generating Combined weekly ${ATTRIB} graph" >&4 start_watchdog ${wdtimer} ${_RRDTOOL} graph \ -W "Combined_W${ATTRIB}" \ --imgformat PNG ${WEBOUT}/Combined/week-${ATTRIB}.png \ --height ${HEIGHT} \ --title "${ATTRIB} - ${wdate}" \ --slope-mode \ --x-grid HOUR:4:DAY:1:DAY:1:432000:%a \ --alt-y-grid \ ${AUTO_SCALE} \ --start -691200 \ ${RRDDEF} \ ${RRDLINE} \ >&5 2>&5 & procid=$! [[ ${debug} -ge 3 ]] && print \ "${myname}/${mypid} DBG: spawned Combined ${_RRDTOOL} PID ${procid}" >&4 return_handler ${procid} ${alarmpid} fi (( count += 1 )) done ${_ECHO} ${wdtimeouts} > ${DBDIR}/WDTimeouts