As I’m currently reworking our large, distributed network monitoring solution, I’m also integrating own plugins for various purposes. The beginning is made by a check plugin for memory consumption on Linux hosts which checks /proc/meminfo directly instead of other checks which usually use frontends like free or top. Besides that, there’s really no magic (and parsing /proc/meminfo isn’t magic as well). You’re able to switch between kilobyte and percentage output, defining warning and critical levels is also possible.
It is sh-compliant, released under the terms of the GPLv2 and as every well written shell script there’s no need to provide any argument at all. For full help use -h or –help.
Give it a try if you like and let me know if it doesn’t work as intended.
Please copy the content below. The script will be reworked and uploaded to Nagios and MonitoringExchange after my vacation at the beginning of July.
#!/bin/sh # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; version 2 of the License only. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA ST_OK=0 ST_WR=1 ST_CR=2 ST_UK=3 wcdiff=0 wclvls=0 PROGNAME=`basename $0` VERSION="Version 1.0," AUTHOR="2009, Mike Adolphs (http://www.matejunkie.com/)" print_version() { echo "$VERSION $AUTHOR" } print_help() { print_version $PROGNAME $VERSION echo "" echo "$PROGNAME is a Nagios plugin to check the current memory usage via" echo "/proc/meminfo. It should work on almost every system where you're" echo "able to cat /proc/meminfo. The script itself is written sh-compliant" echo "and free software under the terms of the GPLv2." echo "" echo "$PROGNAME -s/--style kb/perc [-w/--warning] [-c/--critical]" echo "Options:" echo " -s/--style)" echo " You're able to set the output to kilobyte (kb) or percentage" echo " (perc) values. Please note that other values will result in" echo " termination. Default is: kb" echo " -w/--warning)" echo " Warning level in kb or percent for the amount of used memory." echo " Note that when the style is set to percentage, only values" echo " betweeen 0 and 100 are allowed. Default is: Off." echo " -c/--critical)" echo " Critical level in kb or percent for the amount of used memory." echo " Note that when the style is set to percentage, only values" echo " between 0 and 100 are allowed. Default is: Off." exit $ST_UK } val_wcdiff() { if [ ${lv_wr} -gt ${lv_cr} ] then wcdiff=1 fi } val_wclvls() { if [ $style = "perc" ] then if [ "$lv_wr" -lt 0 -o "$lv_wr" -gt 100 -o "$lv_cr" -lt 0 -o "$lv_cr" -gt 100 ] then wclvls=1 val_wcdiff fi fi } style="kb" while test -n "$1"; do case "$1" in --help|-h) print_help exit $ST_UK ;; --version|-v) print_version $PROGNAME $VERSION exit $ST_UK ;; --style|-s) style=$2 shift ;; --warning|-w) lv_wr=$2 shift ;; --critical|-c) lv_cr=$2 shift ;; *) echo "Unknown argument: $1" print_help exit $ST_UK ;; esac shift done if [ ! -z "$lv_wr" -a ! -z "$lv_cr" ] then val_wcdiff val_wclvls fi if [ $wcdiff = 1 ] then echo "Please adjust levels. The critical level must be higher than the warning level!" if [ $wclvls = 1 ] then echo "Warning and critical level values must be between 0 and 100." fi exit $ST_UK fi if [ $wclvls = 1 ] then echo "Warning and critical level values must be between 0 and 100." exit $ST_UK fi MEM_TOTAL=`grep "^MemTotal" /proc/meminfo|awk '{print $2}'` TMP_MEM_FREE=`grep "^MemFree" /proc/meminfo|awk '{print $2}'` TMP_MEM_USED=`expr $MEM_TOTAL - $TMP_MEM_FREE` BUFFERS=`grep "^Buffers" /proc/meminfo|awk '{print $2}'` CACHED=`grep "^Cached" /proc/meminfo|awk '{print $2}'` P_MEM_FREE=`echo "scale=2; $TMP_MEM_FREE / $MEM_TOTAL * 100" | bc -l | sed 's/.[0-9][0-9]//'` P_MEM_USED=`echo "scale=0; 100 - $P_MEM_FREE" | bc -l` if [ $style = "kb" ] then if [ ! -z "$lv_wr" -a ! -z "$lv_cr" ] then if [ ${TMP_MEM_USED} -ge ${lv_wr} -a ${TMP_MEM_USED} -lt ${lv_cr} ] then echo "WARNING - Total: $MEM_TOTAL kb, Used: $TMP_MEM_USED kb, Free: $TMP_MEM_FREE kb | 'mem_total'=$MEM_TOTAL 'mem_used'=$TMP_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$TMP_MEM_FREE" exit $ST_WR elif [ ${TMP_MEM_USED} -ge ${lv_cr} ] then echo "CRITICAL - Total: $MEM_TOTAL kb, Used: $TMP_MEM_USED kb, Free: $TMP_MEM_FREE kb | 'mem_total'=$MEM_TOTAL 'mem_used'=$TMP_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$TMP_MEM_FREE" exit $ST_CR else echo "OK - Total: $MEM_TOTAL kb, Used: $TMP_MEM_USED kb, Free: $TMP_MEM_FREE kb | 'mem_total'=$MEM_TOTAL 'mem_used'=$TMP_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$TMP_MEM_FREE" exit $ST_OK fi else echo "OK - Total: $MEM_TOTAL kb, Used: $TMP_MEM_USED kb, Free: $TMP_MEM_FREE kb | 'mem_total'=$MEM_TOTAL 'mem_used'=$TMP_MEM_USED 'mem_free'=$TMP_MEM_FREE" exit $ST_OK fi elif [ $style = "perc" ] then if [ ! -z "$lv_wr" -a ! -z "$lv_cr" ] then if [ ${P_MEM_USED} -ge ${lv_wr} -a ${P_MEM_USED} -lt ${lv_cr} ] then echo "WARNING - Used: $P_MEM_USED%, Free: $P_MEM_FREE% | 'mem_used'=$P_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$P_MEM_FREE" exit $ST_WR elif [ ${P_MEM_USED} -ge ${lv_cr} ] then echo "CRITICAL - Used: $P_MEM_USED%, Free: $P_MEM_FREE% | 'mem_used'=$P_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$P_MEM_FREE" exit $ST_CR else echo "OK - Used: $P_MEM_USED%, Free: $P_MEM_FREE% | 'mem_used'=$P_MEM_USED;$lv_wr;$lv_cr 'mem_free'=$P_MEM_FREE" exit $ST_OK fi else echo "OK - Used: $P_MEM_USED%, Free: $P_MEM_FREE% | 'mem_used'=$P_MEM_USED 'mem_free'=$P_MEM_FREE" exit $ST_OK fi else echo "Style (-s) must be either kb (kilobyte) or perc (for percent). kb is" echo "being used as the default behavior when you don't provide the -s option." echo "" echo "For more information try -h or --help!" exit $ST_UK fi
the link ot hte scripts is broken, though I really like the script…
Thanks Andrew, I just deleted the possibility to download the script since it’ll be reworked at the beginning of July. This was one of the first checks I’ve written and it could definitely use some improvements.
It’ll then be uploaded to Nagios and MonitoringExchange afterwards where it can be downloaded as well.
Thanks a lot, it’s perfect !
Added possibility for VSZ and RSS
#!/bin/sh
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
PROGNAME=`basename $0`
VERSION=”Version 1.0,”
AUTHOR=”2009, Mike Adolphs (http://www.matejunkie.com/)”
# 2010-01-28 Christian Westgaard
# Added target vsz and rss
ST_OK=0
ST_WR=1
ST_CR=2
ST_UK=3
process=”cron”
target=”mem”
print_version() {
echo “$VERSION $AUTHOR”
}
print_help() {
print_version $PROGNAME $VERSION
echo “”
echo “$PROGNAME is a Nagios plugin to check a specific process via ps.”
echo “You may provide any string as an argument to match a specific”
echo “process. Please note that the output could be distorted if the”
echo “argument matches various processes, so please make sure to use”
echo “unique strings to match a process.”
echo “”
echo “$PROGNAME -p firefox [-w 10] [-c 20] [-t cpu]”
echo “”
echo “Options:”
echo ” -p/–process)”
echo ” You need to provide a string for which the ps output is then”
echo ” then \”greped\”.”
echo ” -w/–warning)”
echo ” Defines a warning level for a target which is explained”
echo ” below. Default is: off”
echo ” -c/–critical)”
echo ” Defines a critical level for a target which is explained”
echo ” below. Default is: off”
echo ” -t/–target)”
echo ” A target can be defined via -t. Choose between cpu, mem, vsz and rss.”
echo ” Default is: mem”
exit $ST_UK
}
while test -n “$1″; do
case “$1″ in
–help|-h)
print_help
exit $ST_UK
;;
–version|-v)
print_version $PROGNAME $VERSION
exit $ST_UK
;;
–process|-p)
process=$2
shift
;;
–target|-t)
target=$2
shift
;;
–warning|-w)
warning=$2
shift
;;
–critical|-c)
critical=$2
shift
;;
*)
echo “Unknown argument: $1″
print_help
exit $ST_UK
;;
esac
shift
done
get_wcdiff() {
if [ ! -z "$warning" -a ! -z "$critical" ]
then
wclvls=1
if [ ${warning} -gt ${critical} ]
then
wcdiff=1
fi
elif [ ! -z "$warning" -a -z "$critical" ]
then
wcdiff=2
elif [ -z "$warning" -a ! -z "$critical" ]
then
wcdiff=3
fi
}
val_wcdiff() {
if [ "$wcdiff" = 1 ]
then
echo “Please adjust your warning/critical thresholds. The warning \
must be lower than the critical level!”
exit $ST_UK
elif [ "$wcdiff" = 2 ]
then
echo “Please also set a critical value when you want to use \
warning/critical thresholds!”
exit $ST_UK
elif [ "$wcdiff" = 3 ]
then
echo “Please also set a warning value when you want to use \
warning/critical thresholds!”
exit $ST_UK
fi
}
get_vals() {
process=`echo ${process} | sed ‘s/^.\|[a-z][A-Z] /\[&]/g’`
tmp_output=`ps aux | grep “$process” | grep -v $0`
if [ -z "$tmp_output" ]
then
echo “CRITICAL – Process is not running!”
exit $ST_CR
fi
ps_user=`echo ${tmp_output} | awk ‘{print $1}’`
ps_pid=`echo ${tmp_output} | awk ‘{print $2}’ `
ps_cpu=`echo ${tmp_output} | awk ‘{print $3}’`
ps_mem=`echo ${tmp_output} | awk ‘{print $4}’ `
ps_vsz=`echo ${tmp_output} | awk ‘{print $5}’ ` # total VM size in kB
ps_rss=`echo ${tmp_output} | awk ‘{print $6}’ ` # resident set size
ps_start=`echo ${tmp_output} | awk ‘{print $9}’ `
tmp_ps_cputime=`echo ${tmp_output} | awk ‘{print $10}’`
tmp_ps_cpuhours=`echo ${tmp_ps_cputime} | awk -F \: ‘{print $1}’`
tmp_ps_cpumin=`echo ${tmp_ps_cputime} | awk -F \: ‘{print $2}’`
ps_cputime=`echo “scale=0; (${tmp_ps_cpuhours} * 60) + \
${tmp_ps_cpumin}” | bc -l`
}
do_wccalc() {
if [ -n "$warning" -a -n "$critical" ]
then
if [ "$target" = "cpu" ]; then
tmp_wc_target=`echo ${ps_cpu} | awk -F \. ‘{print $2}’`
if [ "$tmp_wc_target" -ge 5 ]
then
wc_target=`echo ${ps_cpu} | awk -F \. ‘{print $1}’`
wc_target=`expr ${wc_target} + 1`
else
wc_target=`echo ${ps_cpu} | awk -F \. ‘{print $1}’`
fi
elif [ "$target" = "mem" ]; then
tmp_wc_target=`echo ${ps_mem} | awk -F \. ‘{print $2}’`
if [ "$tmp_wc_target" -ge 5 ]
then
wc_target=`echo ${ps_mem} | awk -F \. ‘{print $1}’`
wc_target=`expr ${wc_target} + 1`
else
wc_target=`echo ${ps_mem} | awk -F \. ‘{print $1}’`
fi
elif [ "$target" = "vsz" ]; then
wc_target=${ps_vsz}
elif [ "$target" = "rss" ]; then
wc_target=${ps_rss}
fi
fi
}
do_output() {
process=`echo ${process} | sed ‘s/\[//g' | sed 's/\]//g’`
output=”Process: ${process}, User: ${ps_user}, CPU: ${ps_cpu}%, \
RAM: ${ps_mem}%, VSZ: ${ps_vsz}kB, RSS: ${ps_rss}kB, Start: ${ps_start}, CPU Time: ${ps_cputime} min”
}
do_perfdata() {
perfdata=”‘cpu’=${ps_cpu} ‘memory’=${ps_mem} ‘vsz’=${ps_vsz} ‘rss’=${ps_rss} cputime’=${ps_cputime}”
}
# Here we go!
get_wcdiff
val_wcdiff
get_vals
do_wccalc
do_output
do_perfdata
if [ -n "$warning" -a -n "$critical" ]
then
if [ "$wc_target" -ge "$warning" -a "$wc_target" -lt "$critical" ]
then
echo “WARNING – ${output} | ${perfdata}”
exit $ST_WR
elif [ "$wc_target" -ge "$critical" ]
then
echo “CRITICAL – ${output} | ${perfdata}”
exit $ST_CR
else
echo “OK – ${output} | ${perfdata}”
exit $ST_OK
fi
else
echo “OK – ${output} | ${perfdata}”
exit $ST_OK
fi
Thanks a lot !
It works perfectly !
Works great! Thanks a lot!