#!/bin/sh # # Plugin to check system memory # by hugme (nagios@hugme.org) # You can find my checks here: https://github.com/hugme/Nag_checks # Nagios script to check memory usage on linux server # version 2.0.0 # ########################################################## MEMINFO="/proc/meminfo" OOMKILLINFO="/proc/vmstat" ########################################################## # We call them functions because they're fun ########################################################## print_help() { cat << EOF Linux Memory Plugin for Nagios Copyright (c) hugme (nagios@hugme.org) Version: 1.2.0 Last Modified: 10-07-2014 License: This software can be used for free unless I meet you, then you owe me lunch. Usage: check_linux_memory -w [warning %] -c [critical %] Options: -w [0-99] = Your warning %. 20 means 20% of your memory can remain before a warning alarm. Do not use the % sign. -c [0-99] = Your critical %. 10 means 10% of your memory can remain before a critical alarm. Do not use the % sign. -d [K,M,G,T] = divider K=kilobytes, M=megabytes, G=gigabytes, T=terabytes -f = Included for backwards compatability to older versions -n = Don't Include cached memory as free memory when calculating your percentage free -K = Don't check the OutOfMemory Kill counter -k [0-9999] = Threshold for OOMKill alert (default: 0) -A = Don't check awk capabilities (as of 2024: mawk can't printf an integer over 2^31) EOF } invalid_type() { echo "\nInvalid $1\n" print_help exit 3 } ############################################## ## Suck in the user input ############################################## while test -n "$1"; do case $1 in --help) print_help ; exit 0 ;; -A) AWK_CHECK=0 ;; -h) print_help ; exit 0 ;; -w) WARN="$2"; shift ;; -c) CRIT="$2"; shift ;; -d) DIV="$2"; shift ;; -n) NC=1 ;; -k) THRESHOLD_OOMKILL="$2"; shift ;; -K) DISABLE_OOMKILL=1 ;; esac shift done ############################################## ## Set the defaults if needed ############################################## [ -z "$WARN" ] && WARN=20 [ -z "$CRIT" ] && CRIT=10 [ -z "$DIV" ] && DIV=M [ -z "$FC" ] && FC=0 [ -z "$DISABLE_OOMKILL" ] && DISABLE_OOMKILL="" [ -z "$AWK_CHECK" ] && AWK_CHECK=1 [ -z "$THRESHOLD_OOMKILL" ] && THRESHOLD_OOMKILL=0 ############################################## ## Check awk capabilities ############################################## if [ "$AWK_CHECK" -gt 0 ] && [ "$( awk 'BEGIN{ printf "%ld", 3000000000 }' )" != "3000000000" ]; then echo "UNKNOWN this version of awk is not able to display big numbers." exit 3 fi ############################################## ## Check user input ############################################## [ ! -z `echo $WARN | tr -d [:digit:]` ] && invalid_type "Warning: Warning value can only contain numbers" [ ! -z `echo $CRIT | tr -d [:digit:]` ] && invalid_type "Critical: Critical value can only contain numbers" [ "${WARN%.*}" -ge 100 ] && invalid_type "Warning: Warning must be smaller than 100%" [ "${CRIT%.*}" -ge 100 ] && invalid_type "Critical: Critical must be smaller than 100%" [ "${CRIT%.*}" -gt "${WARN%.*}" ] && invalid_type "Critical: Your Warning must be Higher than your Critical" case $DIV in k|K) DIVNUM=1024;; m|M) DIVNUM=1048576;; g|G) DIVNUM=1073741824;; t|T) DIVNUM=1099511627776;; *) invalid_type;; esac [ ! -f "$MEMINFO" ] && { echo "Your Memory info file seems to be missing" exit 1 } if [ -z "$DISABLE_OOMKILL" ] && ! grep '^oom_kill ' "$OOMKILLINFO" >/dev/null 2>&1; then echo "UNKNOWN threshold set for oom_kill but the counter not available in '$OOMKILLINFO'." exit 3 fi ############################################## ## Do the work ## Pull the memory file into awk ## grab the lines we need ## Print the information ############################################## RESULT=$(awk -v warnperct=$WARN -v critperct=$CRIT -v div=$DIV -v divnum=$DIVNUM -v nc=$NC -v disable_oomkill=$DISABLE_OOMKILL -v threshold_oomkill=$THRESHOLD_OOMKILL ' { UnitQuantity["B"]=1 UnitQuantity["kB"]=1024 UnitQuantity["MB"]=1048576 UnitQuantity["GB"]=1073741824 UnitQuantity["TB"]=1099511627776 } /^MemTotal:/ { tot=$2*UnitQuantity[$3] } /^MemFree:/ { free=$2*UnitQuantity[$3] } /^Buffers:/ { buff=$2*UnitQuantity[$3] } /^Cached:/ { cache=$2*UnitQuantity[$3] } /^Active:/ { active=$2*UnitQuantity[$3] } /^Inactive:/ { inactive=$2*UnitQuantity[$3] } /^oom_kill / { oomkill=$2 } END { if ( nc != 1 ) { free=free+cache+buff } { freeperct=free/tot*100 warn=int(warnperct*tot/100) # convert to int to avoid dealing with weird display crit=int(critperct*tot/100) } if ( freeperct > warnperct ) { result="OK" ; xit="0"} if ( freeperct <= warnperct ) { if ( freeperct > critperct ) { result="WARNING" ; xit="1" } else if ( freeperct <= critperct ) { result="CRITICAL" ; xit="2" } } if ( disable_oomkill != 1 ) { oomkill_display=" OOMKills:"oomkill oomkill_perfdata=" oomkill="oomkill";;"threshold_oomkill";0" if ( oomkill > threshold_oomkill ) { result="CRITICAL - Out of memory kills detected" ; xit="2" } } { printf "%d MEMORY %s - %.2f%% Free - Total:%.1f%s", xit, result, freeperct, tot/divnum, div printf " Active:%.1f%s", active/divnum, div printf " Inactive:%.1f%s", inactive/divnum, div printf " Buffers:%.1f%s", buff/divnum, div printf " Cached:%.1f%s", cache/divnum, div printf "%s", oomkill_display printf " |Active=%ldB;;;0;%ld", active, tot printf " Buffers=%ldB;;;0;%ld", buff, tot printf " Cached=%ldB;;;0;%ld", cache, tot printf " Free=%ldB;%ld;%ld;0;%ld", free, warn, crit, tot printf " Inactive=%ldB;;;0;%ld", inactive, tot printf "%s", oomkill_perfdata } }' "$MEMINFO" "$OOMKILLINFO" ) echo ${RESULT#* } exit ${RESULT%% *}