Skip to content
Snippets Groups Projects
Select Git revision
  • 4de9cff4852a86a75d0fa23c68f545afc973ae66
  • master default protected
  • simple-task/7248-eol-check-add-node-22
  • 6877_check_iml_deployment
4 results

check_snmp_synology

Blame
  • inc_pluginfunctions 17.83 KiB
    #!/bin/bash
    # ======================================================================
    #
    # NAGIOS CLIENT CHECK :: FUNCTIONS
    #
    # ----------------------------------------------------------------------
    #
    # Functions 
    #   execIfReady COMMAND [SLEEPTIME] [MAXTRIES]
    #                       execute a command max MAXTRIES times until it returns
    #                       exitcode 0 (or reaches limit)
    #   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.hasParamoption PARAMNAME "$@"
    #                       check if a letter was used as command line option
    #   ph.toUnit VALUE TO-UNIT
    #                       convert value i.e. "12M" into other unit i.e. "K"
    #   ph.setStatus VALUE  set a status
    #   ph.setStatusByLimit VALUE WARNLIMIT CRITLIMIT
    #   ph.status [TEXT]    show status as Text
    #
    #   ph.abort [TEXT]     shows error message and exit with status unknown 
    #   ph.exit             exit plugin (with set statuscode)
    #
    # ----------------------------------------------------------------------
    # 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
    # 2020-09-01  v1.3  <axel.hahn@iml.unibe.ch>  added ph.hasParamoption
    # 2022-08-31  v1.4  <axel.hahn@iml.unibe.ch>  shellfix corrections
    # 2022-10-25  v1.5  <axel.hahn@iml.unibe.ch>  handle empty value in ph.perfadd
    # 2023-01-30  v1.6  <axel.hahn@unibe.ch>      check performance params 5+6 and show a warning if missing
    # 2023-02-16  v1.7  <axel.hahn@unibe.ch>      adding a generic min and max value did not really help
    # 2023-04-24  v1.8  <axel.hahn@unibe.ch>      fix unit conversion
    # 2023-05-05  v1.9  <axel.hahn@unibe.ch>      user specific counter directory
    # 2023-05-17  v1.10 <axel.hahn@unibe.ch>      ph.getOS searches in os-release first
    # 2023-06-22  v1.11 <axel.hahn@unibe.ch>      fix ph.toUnit with float values; shell fixes
    # 2023-08-24  v1.12 <axel.hahn@unibe.ch>      toUnit got 3rd param for count of digits after "."
    # 2023-08-30  v1.13 <axel.hahn@unibe.ch>      reverse return code in ph.hasParamoption to unix like return codes: 0=true; <>0 = false
    # 2023-09-05  v1.14 <axel.hahn@unibe.ch>      ph.require - show error below status line
    # 2023-09-14  v1.15 <axel.hahn@unibe.ch>      add ph.showtimer; fix broken pipe messages in journallog
    # ======================================================================
    
    
    # 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
    
    typeset -i ph_cfg__EXIT_CODE
    
    ph_timer_start=$( date +%s.%N )
    
    declare ph_perfdatafile=
    
    # 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.require(){
      local _out;
      if ! _out=$( which $* 2>&1 ); then
          ph.setStatus "unknown"
          ph.status "$0 requires the following tools to run: $*"
          echo "$_out"
          ph.exit
      fi
    }
    
    # get time in sec and milliseconds since start
    # no parameter is required
    function ph.showtimer(){
      local timer_end; timer_end=$( date +%s.%N )
      local totaltime; totaltime=$( awk "BEGIN {print $timer_end - $ph_timer_start }" )
      local sec_time; sec_time=$( echo "$totaltime" | cut -f 1 -d "." )
      test -z "$sec_time" && sec_time=0
    
      local ms_time; ms_time=$( echo "$totaltime" | cut -f 2 -d "." | cut -c 1-3 )
    
      echo "$sec_time.$ms_time sec"
    }
    
    # ----------------------------------------------------------------------
    # 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(){
      local distro=
    
      if [ -z "$distro" ]; then
        # centos7, debian, manjaro, ubuntu
        distro=$( grep "^ID=" /etc/os-release | cut -f 2 -d "=" )
      fi
    
      if [ -z "$distro" ]; then
        distro=$( grep "^ID=" /etc/*-release | cut -f 2 -d "=" )
      fi
    
      if [ -z "$distro" ]; then
        # debian6,7, ubuntu 10,12 .. maybe unneeded.
        distro=$( head -1 /etc/issue | 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=$( grep -E "^(VERSION_ID|DISTRIB_RELEASE)=" /etc/*-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"
    }
    
    # check if a letter was used as command line option and return as 0 (=no) or 1 (=yes)
    # ph.hasParamoption "h" "$@"
    # param  string  parameter(letter) to test
    # param  string  "$@"
    function ph.hasParamoption(){
      local _sParam=$1
      local _opt
      shift 1
    
      # 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 "abcdefghijklmnopqrstuvwxyz" _opt; do
        # echo "DEBUG: testing $_sParam in ${_opt} ..."
        case "${_opt}" in
          "$_sParam")
            # echo "0"
            return 0
            ;;
        esac
      done
      # echo "1"
      return 1
    }
    
    
    # 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
        _unit=${1//[0-9\.]/}
    
        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" = "T" && echo 2^40
        test "$_unit" = "P" && echo 2^50
    
        # 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
    # param  integer count of digits after "."; default: none (=integer value)
    function ph.toUnit(){
        local _value=$1
        local _unit=$2
        local _digits=${3:-0}
    
        local _multiply; _multiply=$( ph._getExp "$_value" )
        local _divisor;  _divisor=$(  ph._getExp "$_unit"  )
    
        local _bc
        _bc="bc"
    
        local _dots
    
        test $_digits -gt 0 && _dots=$( yes "." 2>/dev/null | head -$_digits | tr -d "\n" )
        test $_digits -gt 0 && _bc+=" -l | grep -o '.*\\.${_dots}'"
    
        echo "$(echo "$_value" | tr -d "[:alpha:]" )*( ${_multiply}/$_divisor )" | eval "$_bc" | sed "s#^\.#0.#"
        
    }
    
    # ----------------------------------------------------------------------
    #
    # 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")))
    }
    
    # get file for storage of last value
    # global  string  dir_data  custom path; default is /tmp/icinga_counter/
    # param   string  varName   variable name of a value to store
    function ph._getStorefile(){
            local varName=$1
    
            local mydir="/tmp/icinga_counter_${USER}"
            test -n "$dir_data" && mydir="${dir_data}/_counter_${USER}"
            local _basename
            _basename=$(basename $0)
    
            test -d "${mydir}" || mkdir -p "${mydir}"
            echo "${mydir}/${_basename}${varName}.lastvalue"
            
    }
    
    # save a value - needed for gdAddDeltaData
    # param   string  varName   variable name of a value to store
    # param   *       value     value as float/ integer
    function ph._savecounter() {
            local varName=$1
            local value=$2
            local sStoreFile; sStoreFile=$(ph._getStorefile "${varName}")
            #echo "DEBUG: `date +%s`:${value} \> ${sStoreFile}"
            # echo "`date +%s`:${value}" > "${sStoreFile}"
            echo ${value} > "${sStoreFile}"
    }
    
    # get age of last storage of a value
    # used in perfdeltaspeed
    # param   string  varName   variable name of a value to store
    function ph._getageoflastvalue() {
            local varName=$1
            local sStoreFile; 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 ))
    }
    # get the last value
    # used in perfdeltaspeed
    # param   string  varName   variable name of a value to store
    function ph._readlastvalue(){
            local varName=$1
            local sStoreFile; 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=$(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
    # param  string    variable name
    # param  integer   value
    # param  string    unit to calculate a speed value per min or per sec; one of s|sec or m|min; default: "s"
    # param  string    optional: flag to return a float value
    function ph.perfdeltaspeed(){
            local varName=$1
            local value=$2
            local deltaUnit=$3
            local isFloat=$4
    
            local bcParam=
    
            typeset -i deltaFactor=1
    
            test "$deltaUnit" = "s"   && deltaFactor=1
            test "$deltaUnit" = "sec" && deltaFactor=1
            test "$deltaUnit" = "m"   && deltaFactor=60
            test "$deltaUnit" = "min" && deltaFactor=60
    
            test "$isFloat" = "float" && bcParam="-l"
    
            # 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; iage=$(ph._getageoflastvalue "${varName}")
                            test "$iage" = "0" && iage=1
    
                            local delta; delta=$(echo "${value}-$lastvalue" | bc $bcParam )
                            local deltaspeed; deltaspeed=$(echo "${delta}*${deltaFactor}/(${iage})" | bc $bcParam)
                            retvalue=$deltaspeed
                    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)"
    }
    
    # add performance data
    #
    # OUTPUT-SYNTAX
    # 'label'=value[UOM];[warn];[crit];[min];[max]
    # procs=401;200;300;0;
    #
    # example
    # ph.perfadd  
    #
    # param  string     label
    # param  int|float  your value
    # param  integer    optional: warning level
    # param  integer    optional: critical level
    # param  integer    optional: min graph value
    # param  integer    optional: max graph value
    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
    
      test -z "$_value" && _value=0
    
      # adding a generic min and max value did not really help
      # test -z "$_min"   && echo "WARNING from ph.perfadd: missing param 5 for minimum - setting it to 0"
      # test -z "$_min"   && _min=0
      # test -z "$_max"   && echo "WARNING from ph.perfadd: missing param 6 for maxiumun - setting it to 100"
      # test -z "$_max"   && _max=100  
      # ... so we add them if tey exist only
      local _minmax=
      test -n "$_min"   && _minmax+=";$_min"
      test -n "$_max"   && _minmax+=";$_max"
    
      # echo "${_label}=${_value};${_w};${_c};${_min};${_max}" >>"${ph_perfdatafile}"
      echo "${_label}=${_value};${_w};${_c}${_minmax}" >>"${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
    function 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 -ge $_iMaxTry ]; then
            rm -f $tmpfile
            ph.setStatus "unknown"
            (
              ph.status "Aborting because command failed $_iMaxTry times: [$_cmd2run] - see $0" 
            ) > /dev/tty
            rm -f $tmpfile
            ph.exit
          fi
          sleep $_iSleeptime
        fi
      done
      cat $tmpfile
      rm -f $tmpfile
    }
    
    # ----------------------------------------------------------------------
    
    # show a header in the help for IML checks
    ph.showImlHelpHeader(){
      cat <<EOF
    ______________________________________________________________________
    
    $( basename $0 | tr [:lower:] [:upper:] )
    v$self_APPVERSION
    
    (c) Institute for Medical Education - University of Bern
    Licence: GNU GPL 3
    
    https://os-docs.iml.unibe.ch/icinga-checks/Checks/$( basename $0 ).html
    ______________________________________________________________________
    EOF
    }
    
    # ----------------------------------------------------------------------
    
    # init
    ph.setStatus "ok"
    
    # ----------------------------------------------------------------------