#!/usr/bin/ksh
#
# Nagios Memory Plugin
#
# Description: Check memory usage
#              The plugin was written and testet on Solaris 8/10
#              and RedHat Enterprise 3/4
#
# Author     : Peter Tuschy
# Version    : 1.5
# Date       : 2009-11-27
# 
# Author     : Elena Slobodnik
# Version    : 1.6
# Date       : 2021-05-12
# Add check of MemAvailable for warning and critical
# https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=34e431b0ae398fc54ea69ff85ec700722c9da773

LANG=C
export LANG

# where we are started
WHERE=`dirname $0`

# setting default exit values
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3
STATE_DEPENDENT=4

# import exit values from utils.sh if we found one
if   [ -f ${WHERE}/utils.sh ] ; then
    . ${WHERE}/utils.sh
elif [ -f ${WHERE}/../utils.sh ] ; then
    . ${WHERE}/../utils.sh
fi

usage() {
    echo "Usage: $0 [-w <free integer|percent>] [-c <free integer|percent>]"
    exit $STATE_UNKNOWN
}

# make no warning or critical default
warning=
critical=

# command line parsing
while [ "$1" != "" ];
do
        case $1 in
        -w)
	    shift
	    wpercent=`echo $1 | tr -d '[:digit:].' 2>/dev/null`
	    warning=`echo $1 | tr -d '%' 2>/dev/null`
	    ;;
        -c)
	    shift
	    cpercent=`echo $1 | tr -d '[:digit:].' 2>/dev/null`
	    critical=`echo $1 | tr -d '%' 2>/dev/null`
	    ;;
	--help|-h)
	    usage
	    ;;
        -*)
	    usage
	    ;;
        *)
	    usage
	    
        esac
        shift
done

# threshold values
if [ ! -z "${critical}" ] ; then
    if [ ${critical} -lt 0 ] ; then
        echo "Critical must be a positive integer."
        exit $STATE_UNKNOWN
    fi
fi

if [ ! -z "${warning}" ] ; then
    if [ ${warning} -lt 0 ] ; then
        echo "Critical must be a positive integer."
        exit $STATE_UNKNOWN
    fi
fi

if [ ! -z "${critical}" -a ! -z "${warning}" ] ; then
    if [ ${critical} -gt ${warning} ] ; then
        echo "critical must be less than warning value."
        exit $STATE_UNKNOWN
    fi
fi


OS=`uname`

case "${OS}" in
    SunOS)
	MEMALLL=`/usr/sbin/prtconf | grep '^Memory size: [0-9]* Megabytes' | tr -d '[:alpha:]:[:space:]'`
	MEMFREE=`vmstat 1 3 | tail -1 | awk '{ print int( ( $5 / 1024 ) + 0.5 ) }'`
	MEM_USED_ZFS=`kstat -p 'zfs::arcstats:c' | awk '{ print int( ( $2 / (1024*1024) ) + 0.5 ) }'`
	if [ -z "$MEM_USED_ZFS" ]; then
		MEM_USED_ZFS="0"
	fi
	;;
    Linux)
	MEMALLL=`grep -E '^MemTotal: +[0-9]* kB' /proc/meminfo | tr -d '[:alpha:]:[:space:]' | awk '{ print int( ( $1 / 1024 ) + 0.5 ) }'`
	MEMFREE=`grep -E '^MemFree: +[0-9]* kB' /proc/meminfo | tr -d '[:alpha:]:[:space:]' | awk '{ print int( ( $1 / 1024 ) + 0.5 ) }'`
	MEMBUFF=`grep -E '^Buffers: +[0-9]* kB' /proc/meminfo | tr -d '[:alpha:]:[:space:]' | awk '{ print int( ( $1 / 1024 ) + 0.5 ) }'`
	MEMCACH=`grep -E '^Cached: +[0-9]* kB' /proc/meminfo | tr -d '[:alpha:]:[:space:]' | awk '{ print int( ( $1 / 1024 ) + 0.5 ) }'`
	MEMAVAIL=`grep -E '^MemAvailable: +[0-9]* kB' /proc/meminfo | tr -d '[:alpha:]:[:space:]' | awk '{ print int( ( $1 / 1024 ) + 0.5 ) }'`
	;;
    *)
	echo "OS ${OS} not supportet by this check"
	exit $STATE_UNKNOWN
esac


# calculate used
MEMUSED=$(echo "$MEMALLL - $MEMFREE" | bc)


#calculate  threshold values if needed
if [ ! -z "$wpercent" ] ; then
    warning=$(echo "${MEMALLL} * ${warning} / 100" | bc)
fi
if [ ! -z "$cpercent" ] ; then
    critical=$(echo "${MEMALLL} * ${critical} / 100" | bc)
fi


case "${OS}" in
    SunOS)
	PERFDATA="used=${MEMUSED};;;0;${MEMALLL} free=${MEMFREE};${warning};${critical};${MEMALLL};0 used_zfs=${MEM_USED_ZFS};;;0;${MEMALLL}"
	PLUGDATA="Memory Usage (free ${MEMFREE}MB / used ${MEMUSED}MB / used by zfs cache ${MEM_USED_ZFS}MB)"
	alerting=$(echo ${MEMFREE} + ${MEM_USED_ZFS} | bc)
	alertlabel="free memory"
	;;
    Linux)
	PERFDATA="available=${MEMAVAIL};${warning};${critical};${MEMALLL};0 used=${MEMUSED};;;0;${MEMALLL} free=${MEMFREE};;;${MEMALLL};0 buffers=${MEMBUFF};;;0;${MEMALLL} cached=${MEMCACH};;;0;${MEMALLL}"
	PLUGDATA="Memory Usage (available ${MEMAVAIL} / free ${MEMFREE}MB / used ${MEMUSED}MB / buffers ${MEMBUFF}MB / cached ${MEMCACH}MB)"
	alerting=$(echo ${MEMAVAIL} | bc)
	alertlabel="available memory"
	;;
    *)
	echo "OS ${OS} not supportet by this check"
	exit $STATE_UNKNOWN
esac




if [ ! -z "${alerting}" ] ; then
    if [ ! -z "${critical}" ] ; then
        if [ ${alerting} -le ${critical} ]; then
            echo "CRITICAL - ${alertlabel} less then ${critical} / ${PLUGDATA} | ${PERFDATA}"
            exit $STATE_CRITICAL
        fi
    fi
    if [ ! -z "${warning}" ] ; then
        if [ ${alerting} -le ${warning} ]; then
            echo "WARNING - ${alertlabel} less then ${warning} / ${PLUGDATA} | ${PERFDATA}"
            exit $STATE_WARNING
        fi
    fi
fi

echo "OK - ${PLUGDATA} | ${PERFDATA}"
exit $STATE_OK

