#!/usr/bin/perl -w # # (c)2002 Jack Coates, jack@monkeynoodle.org # Thanks due to countless scripts posted on the web and to # David Talkington on the shell.scripting@moongroup.com list. # # 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 (or with Nagios); if not, write to the # Free Software Foundation, Inc., 59 Temple Place - Suite 330, # Boston, MA 02111-1307, USA # # # check_multisvc.pl is a Nagios plugin designed to check multiple # services and return a severity value which is based on # the number of services that are down. The services do not need # to be on a single host. Some example usages: # # Servers 1-10 all run Apache on port 80 behind a load balancer. # The load-balanced virtual IP is monitored as a # paging-notification service and each host is monitored as an # email-notification service, but you'd also like to # be paged if fifty percent of the hosts have died. # # Server 11 runs several processes on different ports that all do # the same thing and are load-balanced by an external # application. You don't care if one or two processes die, but # you do want to know if they're all dead. # An external configuration file is required. The file defines # the service-host relationships and individual check # commands that we'll need. Its default location is # check_multisvc.cfg in the nagios config directory, or you # can define its location in hosts.cfg or services.cfg # with check_command check_multisvc.pl!-F /path/to/config/file. # You must edit the .cfg file before this plugin will work. use strict; use Getopt::Long; use vars qw($opt_F $opt_w $opt_c $opt_H); use lib "/usr/lib/nagios/plugins"; use lib "/usr/local/nagios/libexec"; use utils qw($TIMEOUT %ERRORS &print_revision &support); my $PROGNAME = "check_multisvc.pl"; my $state = "OK"; my $counter = "0"; my %config = (); my $key = undef; my $value = undef; my $warn = undef; my $crit = undef; my $check = undef; my $result = undef; my $info = undef; sub print_help () { print "$PROGNAME [-h|--help] Gives this usage statement.\n"; print "[-V|--version] Prints version number.\n"; print "[-F|--filename] /path/to/filename.\n"; print "-w|--warn # Number of failed checks to issue WARN at.\n"; print "-c|--critical # Number of failed checks to issue CRITICAL at.\n"; print "[-H|--host] Optional hostname/IP to pass (use %HOST% in your cfg file).\n"; print "Note: $PROGNAME will look for a config file in /etc/nagios/\n"; print " or /usr/local/nagios/etc/ before failing.\n\n"; &support; exit $ERRORS{'UNKNOWN'}; } sub version () { &print_revision ($PROGNAME,"1.1"); &support; exit $ERRORS{'UNKNOWN'}; } # parse command line for config file, options Getopt::Long::Configure('bundling', 'no_ignore_case'); GetOptions ("V|version" => \&version, "h|help" => \&print_help, "w|warn=n" => \$warn, "c|crit=n" => \$crit, "H|host=s" => \$opt_H, "F|filename=s" => \$opt_F); if ( !defined($opt_F) ) { if (-e '/etc/nagios/check_multisvc.cfg') {$opt_F = "/etc/nagios/check_multisvc.cfg"} elsif (-e '/usr/local/nagios/etc/check_multisvc.cfg') {$opt_F = "/usr/local/nagios/etc/check_multisvc.cfg"} else { print "\nPROBLEM: I need a config file.\n"; &print_help; exit $ERRORS{'UNKNOWN'}; } } # Just in case of problems, let's not hang Nagios my $DEFAULT_SOCKET_TIMEOUT = $TIMEOUT; $SIG{'ALRM'} = sub { print "Timeout Exceeded.\n"; exit $ERRORS{'UNKNOWN'}; }; alarm($TIMEOUT); # read config file and insert values and checks into an hash. open (CONFIG, "<$opt_F") or die "Can't open config file $opt_F.\n"; while () { chomp; # no newline s/#.*//; # no comments s/^\s+//; # no leading white s/\s+$//; # no trailing white next unless length; # anything left? my ($key, $value) = split(/\s+/, $_, 2); if ( defined($key) && defined ($value) ) { $value =~ s/%HOST%/$opt_H/; $config{$key} = $value } } # run the checks. foreach my $key (sort keys (%config)) { if ( $config{$key} ) { open(CMD, "$config{$key} |") or die "Can't execute command $config{$key}.\n"; waitpid($?, 0); while () { ($check,$result,$info) = split(/\s+/, $_, 3); if ($result !~ m/ok/i) { $counter ++ } print "$check, $result, $info, $counter\n"; } close(CMD); } } # count up the results and let Nagios know. if ($counter >= $warn && $counter < $crit) { print "$PROGNAME WARNING"; exit $ERRORS{'WARNING'} } if ($counter >= $crit) { print "$PROGNAME CRITICAL"; exit $ERRORS{'CRITICAL'} } print "$PROGNAME OK"; exit $ERRORS{'OK'};