--- check_oracle 2010-10-07 17:11:31.000000000 +0200 +++ co 2011-08-02 18:23:37.000000000 +0200 @@ -8,18 +8,24 @@ PROGNAME=`basename $0` PROGPATH=`echo $0 | sed -e 's,[\\/][^\\/][^\\/]*$,,'` -REVISION="1.4.15" +REVISION="1.4.15-negativewarncrit" . $PROGPATH/utils.sh +dflt_cachwarn="95%" +dflt_cachcrit="97%" +dflt_tswarn="85%" +dflt_tscrit="95%" +dflt_tsname="SYSTEM" + print_usage() { echo "Usage:" echo " $PROGNAME --tns " echo " $PROGNAME --db " echo " $PROGNAME --login " - echo " $PROGNAME --cache " - echo " $PROGNAME --tablespace " + echo " $PROGNAME --cache [USER] [PASS] [CRITICAL] [WARNING]" + echo " $PROGNAME --tablespace [USER] [PASS] [TABLESPACE] [CRITICAL] [WARNING] [maxbytes]" echo " $PROGNAME --oranames " echo " $PROGNAME --help" echo " $PROGNAME --version" @@ -40,11 +46,11 @@ echo "--login SID" echo " Attempt a dummy login and alert if not ORA-01017: invalid username/password" echo "--cache" - echo " Check local database for library and buffer cache hit ratios" + echo " Check local database for library and buffer cache hit ratios (default warn:$dflt_cachwarn,crit:$dflt_cachcrit)" echo " ---> Requires Oracle user/password and SID specified." - echo " ---> Requires select on v_$sysstat and v_$librarycache" + echo " ---> Requires select on v_\$sysstat and v_\$librarycache" echo "--tablespace" - echo " Check local database for tablespace capacity in ORACLE_SID" + echo " Check local database for tablespace capacity in ORACLE_SID (default warn:$dflt_tswarn,crit:$dflt_tscrit,ts:$dflt_tsname)" echo " ---> Requires Oracle user/password specified." echo " ---> Requires select on dba_data_files and dba_free_space" echo "--oranames Hostname" @@ -54,6 +60,12 @@ echo "--version" echo " Print version and license information" echo "" + echo " / can either be a percentage (ie. '15%') or a size in Mega/Giga/Terabyte (ie. '2G'; dflt: M)" + echo " Prepend the size with minus to be notified for a certain level below the maximum value," + echo " ie. '-2G' to be warned 2G before 'SIZE' (-t) or 'MAXBYTES' (-T) tablespace runs out." + echo "" + echo "If and are left blank, ie. \"\", \`sqlplus -s / as sysdba\` is tried instead." + echo "" echo "If the plugin doesn't work, check that the ORACLE_HOME environment" echo "variable is set, that ORACLE_HOME/bin is in your PATH, and the" echo "tnsnames.ora file is locatable and is properly configured." @@ -66,6 +78,54 @@ support } + +# convert_warncrit_val( warnlevel/critlevel ): returns in either % or units of M, no matter what input the user provided +ReturnVal= +ReturnUnit= +convert_warncrit_val() { + input=$1; totalsize=$2 + tmp=0; tmpunit="" + [ `expr index "$input" "%"` -gt 1 ] && tmp=`echo "scale=0; ${input%*%} * $totalsize" | bc | sed 's/\.[0-9]*$//g'` && tmpunit="%" + if [ "$tmp" = "0" ]; then + [ `expr index "$input" "G"` -gt 1 ] && tmp=$[ ${input%*G}*1000 ] && tmpunit="M" + [ `expr index "$input" "T"` -gt 1 ] && tmp=$[ ${input%*T}*1000*1000 ] && tmpunit="M" + if [ "$tmp" = "0" ]; then # default: M + foo=$input + [ `expr index "$input" "M"` -gt 1 ] && foo=$[ ${input%*M} ] && tmpunit="M" + tmp=$foo + fi + fi + + [ $tmp -lt 0 ] && tmp=$[ $totalsize + $tmp ] # ie. -2G + [ $tmp -lt 0 ] && tmp=0 # ie. the result of the line before was below zero => set to zero. + + ReturnVal=$tmp + ReturnUnit=$tmpunit + return +} + + +# do_warncrit_test(warnlevel, critlevel) +do_warncrit_test() { + convert_warncrit_val $1 100; tmpwarn=$ReturnVal # use "100" as "size" for percentile checks, since we don't have that already + convert_warncrit_val $2 100; tmpcrit=$ReturnVal + + if [ $tmpwarn -lt 0 ]; then # ie. -2G + if [ $tmpwarn -gt $tmpcrit ]; then + echo "UNKNOWN - Warning level is less than Crit" + exit $STATE_UNKNOWN + fi + else + if [ $tmpwarn -gt $tmpcrit ]; then + echo "UNKNOWN - Warning level is more than Crit" + exit $STATE_UNKNOWN + fi + fi +} + + + + case "$1" in 1) cmd='--tns' @@ -171,8 +231,13 @@ #exit $STATE_OK #fi else - echo "${2} Database is DOWN" - exit $STATE_CRITICAL + if [ "${2}" != "" ]; then + echo "${2} - Database is DOWN (or doesn't exist)" + exit $STATE_CRITICAL + else + echo "UNKNOWN - Please supply a database name" + exit $STATE_UNKNOWN + fi fi ;; --login) @@ -188,11 +253,24 @@ fi ;; --cache) - if [ ${5} -gt ${6} ] ; then - echo "UNKNOWN - Warning level is less then Crit" - exit $STATE_UNKNOWN + + [ "$#" -lt 2 ] && print_usage && exit # use empty user/pass for default connection / as sysdba, use empty warncrit for dflt-warncrit + + realwarn=$dflt_cachwarn + realcrit=$dflt_cachcrit + [ "$6" != "" ] && realwarn=$6 + [ "$5" != "" ] && realcrit=$5 + + do_warncrit_test "$realwarn" "$realcrit" + + if [ `expr index "$realwarn" "%"` -lt 1 ]; then + echo "${2} UNKNOWN - cache check can only use % value for warn/crit level." + exit $STATE_UNKNOWN fi - result=`sqlplus -s ${3}/${4}@${2} << EOF + + cmdsqlplus="sqlplus -s / as sysdba" + [ "$3" != "" ] && [ "$4" != "" ] && cmdsqlplus="sqlplus -s ${3}/${4}@${2}" + result=`$cmdsqlplus << EOF set pagesize 0 set numf '9999999.99' select (1-(pr.value/(dbg.value+cg.value)))*100 @@ -210,7 +288,7 @@ buf_hr=`echo "$result" | awk '/^[0-9\. \t]+$/ {print int($1)}'` buf_hrx=`echo "$result" | awk '/^[0-9\. \t]+$/ {print $1}'` - result=`sqlplus -s ${3}/${4}@${2} << EOF + result=`$cmdsqlplus << EOF set pagesize 0 set numf '9999999.99' select sum(lc.pins)/(sum(lc.pins)+sum(lc.reloads))*100 @@ -226,59 +304,105 @@ lib_hr=`echo "$result" | awk '/^[0-9\. \t]+$/ {print int($1)}'` lib_hrx=`echo "$result" | awk '/^[0-9\. \t]+$/ {print $1}'` - if [ $buf_hr -le ${5} -o $lib_hr -le ${5} ] ; then - echo "${2} CRITICAL - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + # for actually usable warn/crit levels with higher precision number + convert_warncrit_val "$realwarn" 10000; compwarn=$ReturnVal # $ReturnUnit is being used directly, should be of same type. + convert_warncrit_val "$realcrit" 10000; compcrit=$ReturnVal + # just snip of the % of the input to get perfdata + perfwarn=${realwarn%*%} + perfcrit=${realcrit%*%} + + newbufhr=`echo "$buf_hrx * 10000" | bc -l | sed 's/\.[0-9]*$//g'` + newlibhr=`echo "$lib_hrx * 10000" | bc -l | sed 's/\.[0-9]*$//g'` + + if [ $newbufhr -le $compcrit -o $newlibhr -le $compcrit ] ; then + echo "${2} CRITICAL - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0; buffer=$buf_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0;" exit $STATE_CRITICAL fi - if [ $buf_hr -le ${6} -o $lib_hr -le ${6} ] ; then - echo "${2} WARNING - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + if [ $newbufhr -le $compwarn -o $newlibhr -le $compwarn ] ; then + echo "${2} WARNING - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0; buffer=$buf_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0;" exit $STATE_WARNING fi - echo "${2} OK - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx%;${6};${5};0;100 buffer=$buf_hrx%;${6};${5};0;100" + echo "${2} OK - Cache Hit Rates: $lib_hrx% Lib -- $buf_hrx% Buff|lib=$lib_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0; buffer=$buf_hrx$ReturnUnit;$perfwarn$ReturnUnit;$perfcrit$ReturnUnit;0;" exit $STATE_OK ;; --tablespace) - if [ ${6} -lt ${7} ] ; then - echo "UNKNOWN - Warning level is more then Crit" - exit $STATE_UNKNOWN - fi - result=`sqlplus -s ${3}/${4}@${2} << EOF + + [ "$#" -lt 2 ] && print_usage && exit # use empty user/pass for default connection / as sysdba, use empty warncrit for dflt-warncrit... + + tsname="$dflt_tsname" + [ -n "$5" ] && tsname="$5" + + realwarn="$dflt_tswarn" + realcrit="$dflt_tscrit" + [ "$7" != "" ] && realwarn="$7" + [ "$6" != "" ] && realcrit="$6" + do_warncrit_test "$realwarn" "$realcrit" + + cmdsqlplus="sqlplus -s / as sysdba" + [ "$3" != "" ] && [ "$4" != "" ] && cmdsqlplus="sqlplus -s ${3}/${4}@${2}" + result=`$cmdsqlplus << EOF set pagesize 0 set numf '9999999.99' -select NVL(b.free,0.0),a.total,100 - trunc(NVL(b.free,0.0)/a.total * 1000) / 10 prc +select ROUND(a.maxi,0) MAXI, ROUND(a.total,0) ALLOCATED, ROUND(a.total-b.free,0) USED, ROUND(b.free,0) FREE, ROUND(a.maxi-a.total+b.free,0) FREEMAXI from ( -select tablespace_name,sum(bytes)/1024/1024 total +select tablespace_name,sum(NVL(bytes,0))/1024/1024 total,sum(NVL(maxbytes,0))/1024/1024 maxi from dba_data_files group by tablespace_name) A LEFT OUTER JOIN -( select tablespace_name,sum(bytes)/1024/1024 free +( select tablespace_name,sum(NVL(bytes,0))/1024/1024 free from dba_free_space group by tablespace_name) B -ON a.tablespace_name=b.tablespace_name WHERE a.tablespace_name='${5}'; +ON a.tablespace_name=b.tablespace_name WHERE a.tablespace_name='${tsname}'; EOF` if [ -n "`echo $result | grep ORA-`" ] ; then error=` echo "$result" | grep "ORA-" | head -1` - echo "CRITICAL - $error" + echo "${2} : ${tsname} CRITICAL - $error" exit $STATE_CRITICAL fi - ts_free=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($1)}'` - ts_total=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($2)}'` - ts_pct=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($3)}'` - ts_pctx=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print $3}'` + ts_total= + ts_used= + ts_free= + if [ "${8}" = "max" ]; then + ts_total=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($1)}'` + ts_used=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($3)}'` + ts_free=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($5)}'` + else + ts_total=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($2)}'` + ts_used=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($3)}'` + ts_free=`echo "$result" | awk '/^[ 0-9\.\t ]+$/ {print int($4)}'` + fi + + if [ "$ts_total" = "" ]; then + echo "${2} : ${tsname} UNKNOWN - no data was returned" + exit $STATE_UNKNOWN + fi + + ts_pctx=`echo "scale=2; $ts_used/$ts_total * 100" | bc -l` + ts_pct=`echo "scale=0; $ts_used/$ts_total * 100" | bc -l` + + # if percentage supplied, use percentage in perfdata + [ `expr index "%" "$realwarn"` -gt 0 ] && ts_total=1 + + convert_warncrit_val "$realwarn" $ts_total; compwarn=$ReturnVal # $ReturnUnit is either % or M for the perfdata + convert_warncrit_val "$realcrit" $ts_total; compcrit=$ReturnVal + + perfused=$ts_pctx + [ "$ReturnUnit" != "%" ] && perfused=$[ $ts_total - $ts_free ] && ReturnUnit="M" + if [ "$ts_free" -eq 0 -a "$ts_total" -eq 0 -a "$ts_pct" -eq 0 ] ; then - echo "No data returned by Oracle - tablespace $5 not found?" + echo "${2} : ${tsname} UNKNOWN - No data returned by Oracle - tablespace ${tsname} not found?" exit $STATE_UNKNOWN fi - if [ "$ts_pct" -ge ${6} ] ; then - echo "${2} : ${5} CRITICAL - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + if [ "$ts_pct" -ge "$compcrit" ] ; then + echo "${2} : ${tsname} CRITICAL - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${tsname}=$perfused$ReturnUnit;$compwarn$ReturnUnit;$compcrit$ReturnUnit;0;" exit $STATE_CRITICAL fi - if [ "$ts_pct" -ge ${7} ] ; then - echo "${2} : ${5} WARNING - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + if [ "$ts_pct" -ge "$compwarn" ] ; then + echo "${2} : ${tsname} WARNING - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${tsname}=$perfused$ReturnUnit;$compwarn$ReturnUnit;$compcrit$ReturnUnit;0;" exit $STATE_WARNING fi - echo "${2} : ${5} OK - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${5}=$ts_pctx%;${7};${6};0;100" + echo "${2} : ${tsname} OK - $ts_pctx% used [ $ts_free / $ts_total MB available ]|${tsname}=$perfused$ReturnUnit;$compwarn$ReturnUnit;$compcrit$ReturnUnit;0;" exit $STATE_OK ;; *)