#!/usr/bin/bash
#
# Nagios CPU Plugin
#
# Description: Check the cpu status and print performace data.
#              The plugin was written and testet on Solaris 8/10
#              and RedHat Enterprise Linux 3/4
#
# Author     : Peter Tuschy
# Version    : 1.20
# Date       : 2010-02-09
# 
# Change single bracket to double bracket for grep on Linux
# Version    : 1.21
# Date       : 2015-09-22


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 <warning>] [-c <critical>] [-s <seconds>]"
    exit $STATE_UNKNOWN
}

# make no warning or critical default
warning=-1
critical=-2
samples=15

# 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`
	    ;;
        -s)
	    shift
	    samples=$1
	    ;;
	--help|-h)
	    usage
	    ;;
        -*)
	    usage
	    ;;
        *)
	    usage
	    
        esac
        shift
done

# CPU threshold values
CPU_WARNING=$warning
CPU_CRITICAL=$critical

if [ $CPU_CRITICAL -ge $CPU_WARNING ]; then
        echo "Critical value must be less than the warning value"
        exit $STATE_UNKNOWN
fi

OS=`uname`
samples2=`expr ${samples} + 2`

case "${OS}" in
    SunOS)
	if [ -x "${WHERE}/current_time" -a -f /tmp/sar.txt ] ; then
	    TCURRENT=`${WHERE}/current_time -65`
	    TSAMPLE=`awk /^SampleTime/'{ printf "%.0f", $2 }' /tmp/sar.txt`
	    if [ $TCURRENT -lt $TSAMPLE ] ; then
		USESAR=/tmp/sar.txt
	    fi
	fi

	if [ -z "${USESAR}" ] ; then
	    VMSTAT=`iostat -l 1 1 ${samples2} | grep -v '[:alpha:]' | tail -${samples} | \
	        awk '{ user += $(NF-3) ; kernel += $(NF-2) ; idle += $(NF) ; wait += $(NF-1) ; count +=1 }
		     END { print ( user / count ) " " ( kernel / count ) " " ( idle / count ) " " ( wait / count ) }'`
	else
	    CPUUSER=`awk /^%usr/'{ printf "%.0f", $2 }' ${USESAR}`
	    CPUSYST=`awk /^%sys/'{ printf "%.0f", $2 }' ${USESAR}`
	    CPUIDLE=`awk /^%idle/'{ printf "%.0f", $2 }' ${USESAR}`
	    CPUWAIT=`awk /^%wio/'{ printf "%.0f", $2 }' ${USESAR}`
	    OUTPUT=`echo $CPUIDLE | awk '{ printf "%.0f", $1 }'`
	    samples=60
	fi
	;;
    Linux)
	if [ -x "${WHERE}/current_time" -a -f /tmp/sar.txt ] ; then
	    TCURRENT=`${WHERE}/current_time -65`
	    TSAMPLE=`awk /^SampleTime/'{ printf "%.0f", $2 }' /tmp/sar.txt`
	    if [ $TCURRENT -lt $TSAMPLE ] ; then
		USESAR=/tmp/sar.txt
	    fi
	fi

	if [ -z "${USESAR}" ] ; then
	
	    # find what sar we have
	    # this is the new one with steal
	    if vmstat 1 1 | grep 'us sy id wa st$' >/dev/null ; then
		VMSTAT=`vmstat 1 ${samples2} | grep -v '[[:alpha:]]' | tail -${samples} | \
		    awk '{ user += $(NF-4) ; kernel += $(NF-3) ; idle += $(NF-2) ; wait += $(NF-1) ; count +=1 }
		     END { print ( user / count ) " " ( kernel / count ) " " ( idle / count ) " " ( wait / count ) }'`
	    # here the old one without steal
	    elif vmstat 1 1 | grep 'us sy id wa$' >/dev/null ; then
		VMSTAT=`vmstat 1 ${samples2} | grep -v '[[:alpha:]]' | tail -${samples} | \
		    awk '{ user += $(NF-3) ; kernel += $(NF-2) ; idle += $(NF-1) ; wait += $(NF) ; count +=1 }
		     END { print ( user / count ) " " ( kernel / count ) " " ( idle / count ) " " ( wait / count ) }'`
	    else
		echo "No matching vmstat data found"
		exit $STATE_UNKNOWN
	    fi
	else
	    CPUUSER=`egrep "^%user|^%nice" ${USESAR} | awk '{ user += $2 } END { printf "%.2f", user }'`
	    CPUSYST=`awk /^%system/'{ printf "%.2f", $2 }' ${USESAR}`
	    CPUIDLE=`awk /^%idle/'{ printf "%.2f", $2 }' ${USESAR}`
	    CPUWAIT=`awk /^%iowait/'{ printf "%.2f", $2 }' ${USESAR}`
	    OUTPUT=`echo $CPUIDLE | awk '{ printf "%.0f", $1 }'`
	    samples=60
	fi
	;;
    *)
	echo "OS ${OS} not supportet by this check"
	exit $STATE_UNKNOWN
esac

if [ -z "${USESAR}" ] ; then
    CPUUSER=`echo $VMSTAT | awk '{ printf "%.2f", $1 }'`
    CPUSYST=`echo $VMSTAT | awk '{ printf "%.2f", $2 }'`
    CPUIDLE=`echo $VMSTAT | awk '{ printf "%.2f", $3 }'`
    CPUWAIT=`echo $VMSTAT | awk '{ printf "%.2f", $4 }'`
    OUTPUT=`echo $VMSTAT | awk '{ printf "%.0f", $3 }'`
fi

PERFDATA="user=${CPUUSER};;;0;100    system=${CPUSYST};;;0;100    idle=${CPUIDLE};${CPU_WARNING};${CPU_CRITICAL};100;0    wait=${CPUWAIT};;;0;100"
PLUGDATA="CPU average for ${samples} seconds (idle ${CPUIDLE}% / user ${CPUUSER}% / system ${CPUSYST}% / iowait ${CPUWAIT}%)"


if [ $OUTPUT -le $CPU_CRITICAL ]; then

        echo "CPU CRITICAL - ${PLUGDATA} | ${PERFDATA}"
        exit $STATE_CRITICAL

elif [ $OUTPUT -le $CPU_WARNING ]; then

        echo "CPU WARNING - ${PLUGDATA} | ${PERFDATA}"
        exit $STATE_WARNING

elif [ $CPU_WARNING -lt $OUTPUT ]; then

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

        echo "CPU STATUS UNKNOWN"
        exit $STATE_UNKNOWN

fi
