#!/usr/bin/env bash # # Copyright Hari Sekhon 2008 # # 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 # # Nagios Plugin to check multiple processes and their arguments in a single check # Relies on the check_procs plugin from the Nagios Plugins standard distribution set -u title="Check MultiProcs - Nagios Plugin to test multiple processes and their arguments in one check" version="0.6" versioninfo="$title Author: Hari Sekhon Version: $version " # Standard Nagios exit codes OK=0 WARNING=1 CRITICAL=2 UNKNOWN=3 CHECK_PROCS="" test_name="MULTIPROCS " # Paths to look for check_procs in priority order check_procs_paths=" /usr/lib/nagios/plugins/check_procs /usr/nagios/libexec/check_procs " # Shortcut functions for convenience. # Override the test_name above to customize OK(){ message="${@:-Service OK}" echo "${test_name}OK: $message" exit $OK } WARNING(){ message="${@:-Service in Warning State}" echo "${test_name}WARNING: $message" exit $WARNING } CRITICAL(){ message="${@:-Service in Critical State}" echo "${test_name}CRITICAL: $message" exit $CRITICAL } UNKNOWN(){ message="${@:-Service in Unknown State}" echo "${test_name}UNKNOWN: $message" exit $UNKNOWN } usage(){ echo "$versioninfo usage: ${0##*/} -c procs.conf [ -b /path/to/check_procs ] [ -s ] [ -v ] Options: -c --conf The path to the configuration file to use for the test -b --binary Specifies the path to the check_procs binary from the Nagios Plugins standard distribution. Optional. Use this if your check_procs is not in your path. If given, overrides check_procs found in path. -s --syntax-check Test the syntax of the given config file but do not execute any tests. Returns OK is the syntax passes or CRITICAL if there are any syntax errors -v --verbose Increase verbosity. Use once to see process details, twice for a little output about what the plugin is doing and three times (or -vvv) for full debug output == Configuration file format == The procs.conf file defines the processes and their arguments, one per line. Each line will effectively be passed to the standard check_procs plugin from the standard distribution processname,arguments,warn,crit These all map to the standard arguments of check_procs. warn and crit should be ranges (eg 1:5) or they can be blank but you must still have the commas delimiting those blank entries eg (process,args,,) See check_procs for more details on options. - Hashes comment out the rest of the line in standard unix tradition - Leading and trailing whitespace around each comma delimited item is ignored for you formatting convenience processname2 , arguments , warn , crit You can omit either warn or crit, but you must have one or the other, otherwise the test would effectively be null and always return OK, so this is not allowed as it serves no useful purpose and is almost certainly a configuration error. == Example Config file == #Process, Arguments , Warn , Crit bash , scriptA.sh argX argY argZ , 1:2 , perl , scriptB.pl -s action , , 3:3 python , scriptC.py -s action , 2:3 , 1:5 logger , -t Name -p user.notice , 1:1 , " exit $UNKNOWN } conf="" continue="false" verbosity=0 binary_set=0 syntax_only=0 while [ $# -ge 1 ]; do case "$1" in -h|--help) usage ;; -b|--binary) [ $# -lt 2 ] && usage if [ "$binary_set" -eq 1 ]; then echo "Arg Error: check_procs supplied twice" usage fi CHECK_PROCS="$2" binary_set=1 shift ;; -c|--conf) [ $# -lt 2 ] && usage if [ -n "$conf" ]; then echo "Arg Error: config supplied twice" usage fi conf="$2" shift ;; -s|--syntax-check) syntax_only=1 ;; -v|--verbose) let verbosity+=1 ;; -vv) let verbosity+=2 ;; -vvv) let verbosity+=3 ;; *) usage ;; esac shift done [ $verbosity -ge 3 ] && echo "$versioninfo" [ -z "$conf" ] && usage [ -f "$conf" ] || UNKNOWN "config file '$conf' could not be found" [ -r "$conf" ] || UNKNOWN "config gile '$conf' is not readable, please check permissions on the file" # Syntax check on conf file config="`sed 's/#.*$//' < "$conf"|grep -v -e "^$" -e "^\s*$"`" function check_syntax(){ while read line; do if [ $syntax_only -eq 1 ]; then syntax_error=CRITICAL else syntax_error=UNKNOWN fi if ! echo "$line" | grep -qP "^\s*[A-Za-z0-9_\.-]+\s*,[A-Za-z0-9_\.\s/-]*,\s*(\d+(:\d+)?)?\s*(,\s*(\d+(:\d+)?)?\s*)?$"; then [ $verbosity -ge 2 ] && echo "Error in line: $line" eval $syntax_error "Syntax Error in configuration file: line `grep -nh "$line" "$conf"|head -n1|sed 's/:.*//'`" fi warn=`echo $line|awk -F, '{print $3}'|sed 's/^\s*//;s/\s*$//'` crit=`echo $line|awk -F, '{print $4}'|sed 's/^\s*//;s/\s*$//'` if [ -z "$warn" -a -z "$crit" ]; then $syntax_error "Config invalid in configuration file: line `grep -nh "$line" "$conf"|head -n1|sed 's/:.*//'` - missing both warn and crit thresholds, this makes this a null test which is pointless. You must supply at least one of warn/crit to be valid, otherwise the test would always be OK regardless of what is tested..." fi if [ -n "$warn" ] && ! echo "$warn" | grep -qP "^\d+:\d+$"; then $syntax_error "Config invalid in configuration file: line `grep -nh "$line" "$conf"|head -n1|sed 's/:.*//'` - warn value is invalid, must be a range value in the form of min_number:max_number to have effect in check_procs" fi if [ -n "$crit" ] && ! echo "$crit" | grep -qP "^\d+:\d+$"; then $syntax_error "Config invalid in configuration file: line `grep -nh "$line" "$conf"|head -n1|sed 's/:.*//'` - crit value is invalid, must be a range value in the form of min_number:max_number to have effect in check_procs" fi done <<< "$config" } if [ $syntax_only -eq 1 ];then check_syntax OK "syntax OK" fi if [ "$binary_set" -eq 0 ]; then if which check_procs >/dev/null 2>&1; then [ $verbosity -ge 2 ] && echo "found check_procs in path, using this for test(s)" CHECK_PROCS="check_procs" else for x in $check_procs_paths; do if [ -f "$x" ]; then [ $verbosity -ge 2 ] && echo "found '$x', using this for test(s)" CHECK_PROCS="$x" break fi done fi fi [ -z "$CHECK_PROCS" -a "$binary_set" -eq 0 ] && UNKNOWN "Cannot find check_procs in path. Please use the -b switch to point to it" [ -z "$CHECK_PROCS" -a "$binary_set" -eq 1 ] && UNKNOWN "please specify the path to check_procs when using the -b switch" [ "`basename $CHECK_PROCS`" != "check_procs" ] && UNKNOWN "'$CHECK_PROCS' is not the right command name, please specify the path to check_procs instead" [ -f "$CHECK_PROCS" ] || UNKNOWN "'$CHECK_PROCS' cannot be found" [ -x "$CHECK_PROCS" ] || UNKNOWN "'$CHECK_PROCS' is not set executable. Possibly chmod +x '$CHECK_PROCS'?" [ $verbosity -ge 2 ] && echo "using config file: $conf" if [ $verbosity -ge 3 ]; then echo "$config" echo "==================================== config ====================================" echo fi check_syntax test_procs(){ total_output="" err_output="" end_result=-1 while read line; do prog=`echo $line|awk -F, '{print $1}'|sed 's/^\s*//;s/\s*$//'` args=`echo $line|awk -F, '{print $2}'|sed 's/^\s*//;s/\s*$//'` warn=`echo $line|awk -F, '{print $3}'|sed 's/^\s*//;s/\s*$//'` crit=`echo $line|awk -F, '{print $4}'|sed 's/^\s*//;s/\s*$//'` [ -n "$warn" ] && warn="-w $warn" [ -n "$crit" ] && crit="-w $crit" [ $verbosity -ge 3 ] && echo "running: \"$CHECK_PROCS\" -C \"$prog\" -a \"$args\" $warn $crit" output="`"$CHECK_PROCS" -C "$prog" -a "$args" $warn $crit`" result=$? if [ $verbosity -ge 3 ]; then echo "raw output: $output" echo "exit code: $result" echo fi [ $result -gt $end_result ] && end_result=$result total_output="${total_output}${output}, " if [ $result -ne "$OK" ]; then err_output="${err_output}${output}, " fi done <<< "$config" } test_procs err_output="${err_output%, }" total_output="${total_output%, }" err_output="`echo "$err_output"|sed 's/PROCS \w\+: //g'`" total_output="`echo "$total_output"|sed 's/PROCS \w\+: //g'`" if [ $end_result -ne $OK -a $verbosity -eq 0 ]; then total_output="$err_output" fi if [ $end_result -eq $OK ]; then [ $verbosity -lt 1 ] && total_output="All processes running" OK "$total_output" elif [ $end_result -eq $WARNING ]; then WARNING "$total_output" elif [ $end_result -eq $CRITICAL ]; then CRITICAL "$total_output" else UNKNOWN "$total_output" fi