Select Git revision
inc_pluginfunctions
inc_pluginfunctions 12.69 KiB
#!/bin/bash
# ======================================================================
#
# NAGIOS CLIENT CHECK :: FUNCTIONS
#
# ----------------------------------------------------------------------
#
# Functions
# ph.abort [TEXT] shows error message and exit with status unknown
# ph.exit exit plugin (with set statuscode)
# ph.getOS get operating system as lowercase - centos|debian|ubuntu|...
# ph.getOSMajor get OS Major version as integer, i.e. 7 on a CentOS7
# ph.getValueWithParam VALUE PARAMNAME "$@"
# return default value or its override from command line
# ph.setStatus VALUE set a status
# ph.setStatusByLimit VALUE WARNLIMIT CRITLIMIT
# ph.status [TEXT] show status as Text
#
# ----------------------------------------------------------------------
# 2016-09-23 added getOS
# 2019-10-29 added setExitcode
# 2020-03-05 v1.2 <axel.hahn@iml.unibe.ch> switch to ph.* helper functions
# ======================================================================
# nagios exit code values
typeset -i ph_cfg__EXIT_OK=0
typeset -i ph_cfg__EXIT_WARNING=1
typeset -i ph_cfg__EXIT_CRITICAL=2
typeset -i ph_cfg__EXIT_UNKNOWN=3
declare ph_perfdatafile=
declare -a ph_perfdata
typeset -i ph_perfcounter=0
# abort a check and exit with status "unknown"
function ph.abort(){
ph.setStatus "unknown"
echo $*
ph.exit
}
# check required binaries in the path
# param(s) string name of binary to check with "which" command
function ph.reqire(){
which $* >/dev/null
if [ $? -ne 0 ]; then
ph.setStatus "unknown"
ph.status "$0 requires the following tools to run: $*"
ph.exit
fi
}
# ----------------------------------------------------------------------
# exit a check plugin
function ph.exit(){
# echo ______________________________________________________________________
# echo "DEBUG: $0 $* -- leaving with _rc = $ph_cfg__EXIT_CODE -- Status $ph_cfg__EXIT_STATUS"
ph.perfshow
exit $ph_cfg__EXIT_CODE
}
# ----------------------------------------------------------------------
# detect LINUX DISTRO as lowercase
# returns one of centos|debian|ubuntu|...
function ph.getOS(){
distro=
if [ -z $distro ]; then
# centos7, debian, manjaro, ubuntu
distro=`cat /etc/*-release | grep "^ID=" | cut -f 2 -d "="`
fi
if [ -z $distro ]; then
# debian6,7, ubuntu 10,12 .. maybe unneeded.
distro=`cat /etc/issue | head -1 | grep "^[a-zA-Z]" | cut -f 1 -d " "`
fi
# sanitize: lowercase, remove "
distro=`echo $distro | tr -d '"' | tr [:upper:] [:lower:]`
if [ -z $distro ]; then
ph.abort "UNKNOWN: distro was not detected."
fi
echo "$distro"
}
# get OS MajorRelease
# returns an integer, i.e. 7 on CentOS7
function ph.getOSMajor(){
local _version=
_version=`cat /etc/*-release | egrep "^(VERSION_ID|DISTRIB_RELEASE)=" | head -1 | cut -f 2 -d "=" | sed 's#"##g' | cut -f 1 -d "."`
if [ -z "$_version" ]; then
_version="?"
exit 1
fi
echo $_version
}
# helper to use the default _value or override it with a found param
# getValueWithParam [default] [parameter] "$@"
function ph.getValueWithParam(){
local _value=$1
local _sParam=$2
local _opt
shift 2
# trick I: allows ${_sParam} in case .. esac section
shopt -s extglob
# trick II: allows usage of getopts multiple times
OPTIND=1
# trick III: changing getops params with a single param do not work ...
# while getopts ":$_sParam:" opt; do
while getopts ":a:b:c:d:e:f:g:h:i:j:k:l:m:n:o:p:q:r:s:t:u:v:w:x:y:z:" _opt; do
# echo "DEBUG: testing ${opt} ..."
case "${_opt}" in
$_sParam)
_value=$OPTARG
;;
esac
done
echo $_value
}
# set an exitcode for the plugin
#
# example:
# in your plugin set an exitcode:
# ph.setStatus "ok"
#
# param integer|string 0..3 or ok|warning|critical|unknown
function ph.setStatus(){
case $1 in
$ph_cfg__EXIT_OK|"ok"):
ph_cfg__EXIT_CODE=$ph_cfg__EXIT_OK
ph_cfg__EXIT_STATUS="OK"
;;
$ph_cfg__EXIT_WARNING|"warning"):
ph_cfg__EXIT_CODE=$ph_cfg__EXIT_WARNING
ph_cfg__EXIT_STATUS="WARNING"
;;
$ph_cfg__EXIT_CRITICAL|"critical"):
ph_cfg__EXIT_CODE=$ph_cfg__EXIT_CRITICAL
ph_cfg__EXIT_STATUS="CRITICAL"
;;
$ph_cfg__EXIT_UNKNOWN|"unknown"):
ph_cfg__EXIT_CODE=$ph_cfg__EXIT_UNKNOWN
ph_cfg__EXIT_STATUS="UNKNOWN"
;;
*)
ph.abort "ERROR: wrong usage ... Status code [$1] is unknown ... please fix the plugin $0."
esac
}
# set exit status by given _value and limits for warning and critical
# it works in both directions with limits on lower end and higher end to
# The mode is detected by given warning and critical limit
# param integer _value of a test
# param integer warning level
# param integer critical level
function ph.setStatusByLimit(){
typeset -i local _value=$1
typeset -i local _iWarnLimit=$2
typeset -i local _iCriticalLimit=$3
if [ $_iWarnLimit -gt $_iCriticalLimit ]; then
_iWarnLimit=-$_iWarnLimit
_iCriticalLimit=-$_iCriticalLimit
_value=-$_value
fi
if [ $_value -lt $_iWarnLimit ]; then
ph.setStatus "ok"
else
if [ $_value -ge $_iCriticalLimit ]; then
ph.setStatus "critical"
else
ph.setStatus "warning"
fi
fi
}
# show status as OK|WARNING|CRITICAL|UNKNOWN
# if you add params it will be shown behind with added carriage return
# without additional params there is NO carriage return
#
# Example
# ph.status
# echo what was tested here
# is the same like
# ph.status "what was tested here"
#
function ph.status(){
echo -n "${ph_cfg__EXIT_STATUS}"
test $# -gt 0 && echo ": $*"
}
# ----------------------------------------------------------------------
#
# convert binary units
#
# ----------------------------------------------------------------------
# helper function for ph.toUnit: get scaling factor
# example: 12M returns 2^30 from ending "M"
# param value with ending scale [none]=1 K=Kilo M=Mega G=Giga
function ph._getExp(){
local _unit=`echo $1 | sed "s#[0-9]##g"`
test -z "$_unit" && echo 1
# binary
test "$_unit" = "K" && echo 2^10
test "$_unit" = "M" && echo 2^20
test "$_unit" = "G" && echo 2^30
test "$_unit" = "P" && echo 2^40
# phyiscal
# test "$_unit" = "m" && echo 10^-3
# test "$_unit" = "c" && echo 10^-2
# test "$_unit" = "d" && echo 10^-1
# test "$_unit" = "k" && echo 10^3
# test "$_unit" = "M" && echo 10^6
# test "$_unit" = "G" && echo 10^9
# echo "ERROR: unsupported value: $_value"
# exit 1
}
# convert a given binary value into another unit
# example $( ph.toUnit 12M K ) converts 12 M(ega) into K(ilo)
# --> return value will be 12288 (without K as suffix)
#
# param string value with optional single letter for unit, i.e. 12M
# param char target unit
function ph.toUnit(){
local _value=$1
local _unit=$2
local _multiply=`ph._getExp $_value`
local _divisor=`ph._getExp $_unit`
# echo "DEBUG ... $_divisor .. $_multiply"
echo "`echo $_value | tr -d "[:alpha:]" `*${_multiply}/$_divisor" | bc
}
# ----------------------------------------------------------------------
#
# performance data
#
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
# PRIVATE FUNCTIONS
# ----------------------------------------------------------------------
# get age of a file in sec
# param string filename to test
#
function ph.getFileAge(){
echo $(($(date +%s) - $(date +%s -r "$1")))
}
function ph._getStorefile(){
local varName=$1
local mydir="/tmp/icinga_counter"
test -z $dir_data || mydir="${dir_data}/_counter"
local _basename=`basename $0`
test -d ${mydir} || mkdir -p ${mydir}
echo "${mydir}/${_basename}${varName}.lastvalue"
}
# save a value - needed for gdAddDeltaData
function ph._savecounter() {
local varName=$1
local value=$2
local sStoreFile=`ph._getStorefile "${varName}"`
#echo "DEBUG: `date +%s`:${value} \> ${sStoreFile}"
# echo "`date +%s`:${value}" > "${sStoreFile}"
echo ${value} > "${sStoreFile}"
}
function ph._getageoflastvalue() {
local varName=$1
local sStoreFile=`ph._getStorefile "${varName}"`
ph.getFileAge "${sStoreFile}"
# local ilast=`cat "${sStoreFile}" 2>/dev/null | cut -f 1 -d ":" `
# local inow=`date +%s`
# echo $(( ${inow}-${ilast}+1 ))
}
function ph._readlastvalue(){
local varName=$1
local sStoreFile=`ph._getStorefile "${varName}"`
# cat "${sStoreFile}" 2>/dev/null | cut -f 2 -d ":"
cat "${sStoreFile}" 2>/dev/null
}
# init usage for performance data
# it creates a filename based on the started check script
function ph._perfinit(){
local _basename=`basename $0`
ph_perfdatafile="/tmp/perfdata_`echo $_basename | sed "s#[^a-z0-9\-]#_#g"`"
rm -f "${ph_perfdatafile}" 2>/dev/null
}
# generate label for performance data value
function ph._getperflabel(){
echo $1 | tr [:upper:] [:lower:] | sed "s#[^a-z0-9\-]##g"
}
# get speed of change of a counter value
# param1: string variable name
# param2: integer value
function ph.perfdeltaspeed(){
local varName=$1
local value=$2
typeset -i newvalue=0
# get last value
local lastvalue=`ph._readlastvalue "${varName}"`
if [ "$lastvalue" = "" ]; then
# retvalue="[no last value]"
retvalue=""
else
local f=1
if [ $value -lt 0 ]; then
f=-1
fi
if [ $(( $lastvalue * $f )) -gt $(( $value * $f )) ]; then
# retvalue="[reset data]"
retvalue=""
else
local iage=`ph._getageoflastvalue "${varName}"`
test $iage = 0 && iage=1
local delta=$(( ${value}-$lastvalue ))
local newvalue=$(( ${delta}/(${iage}) ))
retvalue=$newvalue
fi
fi
ph._savecounter "${varName}" "${value}"
#echo DEBUG sData="${sData} '${varName}'=${retvalue}"
# sGDData="${sGDData} '${varName}'=${retvalue}"
echo ${retvalue}
# DEBUG - wird in Nagios sichtbar
# gdAddLabel "... ${varName} absolute: ${value} -> delta: ${delta} -> derive: ${retvalue} ($iage sec)"
}
# W.I.P.
# add performance data with total counters and store change speed of it
# i.e. network byte or package counter in /proc/net/dev
#
# OUTPUT-SYNTAX
# 'label'=value[UOM];[warn];[crit];[min];[max]
# procs=401;200;300;0;
#
# example
# ph.perfadd
function ph.perfaddtotal(){
local _label=`ph._getperflabel "$1"`
local _value=$2
local _w=$3
local _c=$4
local _min=$5
local _max=$6
ph.perfadd
echo "${_label}=${_value};${_w};${_c};${_min};${_max}" >>${ph_perfdatafile}
}
# add performance data
#
# OUTPUT-SYNTAX
# 'label'=value[UOM];[warn];[crit];[min];[max]
# procs=401;200;300;0;
#
# example
# ph.perfadd
function ph.perfadd(){
if [ -z "$ph_perfdatafile" ]; then
ph._perfinit
fi
local _label=`ph._getperflabel "$1"`
local _value=$2
local _w=$3
local _c=$4
local _min=$5
local _max=$6
if [ -z "$_min" ]; then
_min=0
fi
echo "${_label}=${_value};${_w};${_c};${_min};${_max}" >>${ph_perfdatafile}
}
# output of performance data
# remark: this function is called in ph.exit too
function ph.perfshow(){
if [ ! -z "$ph_perfdatafile" ]; then
if [ -f "$ph_perfdatafile" ]; then
echo -n " |"
cat ${ph_perfdatafile} | tr "\n" " "
rm -f ${ph_perfdatafile}
fi
fi
}
# ----------------------------------------------------------------------
# execute a command and repeat it N times before aborting
# param string command line to execute
# param integer sleeptime in sec before repeating again; default: 5
# param integer max number of tries; default: 3
ph.execIfReady(){
local _cmd2run=$1
local _iSleeptime=${2:-5}
local _iMaxTry=${3:-3}
typeset -i local _iCount=0
typeset -i local _rc=1
local tmpfile=/tmp/execIfRead_out_$$
while [ $_rc -ne 0 ]; do
eval "${_cmd2run}" >$tmpfile 2>&1
_rc=$?
if [ $_rc -ne 0 ]; then
_iCount=$_iCount+1
if [ $_iCount -gt $_iMaxTry ]; then
rm -f $tmpfile
ph.setStatus "unknown"
(
ph.status "Aborting because command failed $_iMaxTry times: [$_cmd2run] - see $0"
) > /dev/stdout
rm -f $tmpfile
ph.exit
fi
sleep $_iSleeptime
fi
done
cat $tmpfile
rm -f $tmpfile
}
# ----------------------------------------------------------------------
# init
ph.setStatus "ok"
# ----------------------------------------------------------------------