#!/usr/bin/perl # Copyright (C) 2001-2002 Eric Bollengier # # This program and documentation is free software; you can redistribute # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # $Id: srvcheck.cgi,v 1.4 2004/01/30 10:38:24 eric Exp $ # Nagios is a registered trademark of Ethan Galstad. ################################################################ ## # README : # This cgi can do service check on demand # Only authorized_for_system_commands users can use this cgi # You can update service status with nsca if the test ran ok # INSTALL : # copy this file in $prefix/cgi (where prefix is nagios install dir) # do a chmod +x $prefix/cgi/srvcheck.cgi # add something like # [root@plume ssi]# cat /usr/share/nagios/ssi/extinfo-header.ssi # Test Service NOW
################################################################ # user configuration our $cgi_cfg = '/etc/nagios/cgi.cfg' ; # if you want update nagios engine with OK result our $nsca_cmd = '/usr/local/nsca/bin/send_nsca.disable' ; our $nsca_arg = '-H localhost -c /usr/local/nsca/etc/send_nsca.cfg' ; ################################################################ use strict; use CGI qw/:standard/; use CGI::Util qw/unescape/ ; our %cfg_cmd ; # commands.cfg our %cfg_res ; # ressources.cfg our %cfg_host ; # hosts.cfg our %cfg_srv ; # services.cfg our %cfg_main ; # nagios.cfg our %cfg_hostgrp ; # hostgroups.cfg our %cfg_srvhostgrp ; our %cfg_hostsrv ; # host:(srv1,srv2,srv3) our $host ; # cgi param host our $serv ; # cgi param service our $hostgrp ; # cgi param hostgroup our $last_url ; # http referer our $user ; # http user our @tmp ; our $nsca_txt ; my @class_return = ('statusOK', 'statusBGWARNING', 'statusBGCRITICAL') ; my @code_return = ('OK', 'Warning', 'Critical') ; ################################################################ # read nagios.cfg ('cfg_file' is an array) sub process_cfg { my ($file) = @_ ; my %cfg ; open(FP, "$file") or die "Erreur d'acces sur $file $!" ; while() { next if (/^\#/) ; next if (!/^([a-z_-]+)=(.+?)$/) ; $cfg{$1} = $2 ; } close(FP) ; die "Pb in cgi.cf : pas de nagios.cfg" unless (defined $cfg{'main_config_file'}) ; open(FP, $cfg{'main_config_file'}) or die "Erreur sur $cfg{'main_config_file'} $!" ; while() { next if (/^\#/) ; next if (!/^([a-z_-]+)=(.+?)$/) ; if ($1 eq 'cfg_file') { push @{$cfg{'cfg_file'}}, $2 ; } else { $cfg{$1} = $2 ; } } close(FP) ; return %cfg ; } ################################################################ # read all files in @_ and create %cfg_xxx sub process_objects { my (@files) = @_ ; my $f ; my $i ; my $cur ; my $type ; foreach $f (@files) { open(FP, $f) or next ; $cur = {} ; while() { if (/^\s*\}/) { if ($type eq 'host') { if (defined $cur->{'register'} and $cur->{'register'}==0) { $cfg_host{$cur->{'name'}} = $cur ; } else { $cfg_host{$cur->{'host_name'}} = $cur ; } } elsif ($type eq 'service') { if (defined $cur->{'register'} and $cur->{'register'}==0) { $cfg_srv{$cur->{'name'}} = $cur ; } foreach my $h (split(/,/,$cur->{'host_name'})) { $cfg_srv{"$h:$cur->{'service_description'}"} = $cur ; push @{$cfg_hostsrv{$h}},$cur->{'service_description'}; } foreach my $g (split(/,/, $cur->{'hostgroup_name'})) { $cfg_srvhostgrp{"$g:$cur->{'service_description'}"}=$cur; } } elsif ($type eq 'command') { $cfg_cmd{$cur->{'command_name'}} = $cur ; } elsif($type eq 'hostgroup') { $cfg_hostgrp{$cur->{'hostgroup_name'}} = $cur ; } $cur = {} ; $type = '' ; } elsif (/^define\s+(\w+)/) { $type = $1 ; next ; } elsif (/^\s*([\w_]+)\s+(.*?)$/) { $cur->{$1} = $2 ; next ; } } close(FP) ; } # for each service group we add a host service foreach my $key (%cfg_srvhostgrp) { my ($group, $serv) = split(/:/,$key) ; foreach my $h (split(/,/, $cfg_hostgrp{$group}->{'members'})) { $cfg_srv{"$h:$cfg_srvhostgrp{$key}->{'service_description'}"} = $cfg_srvhostgrp{$key} ; } } } ################################################################ # read ressources.cfg # return %cfg_res sub process_ressources { my ($file) = @_ ; my %res ; open(FP, "$file") or die "Error access on $file $!" ; while() { next if (/^\#/) ; next if (!/^([\$\w_-]+)=(.+?)$/) ; $res{$1} = $2 ; } close(FP) ; return %res ; } ################################################################ # replace $HOSTADDRESS$, $ARG1$.., $USER1$... in command_line # return : command_line sub process_macro { my ($host, $service) = @_ ; my $template = $cfg_host{$cfg_host{$host}->{'use'}} ; my ($cmd, $cmd_t) ; if ($template) { $cmd_t = $cfg_host{$template}->{'check_command'} ; } $cmd = $cfg_srv{"$host:$service"}{'check_command'} || $cmd_t; return '' unless ($cmd) ; my ($command, @arg) = split(/!/, $cmd) ; my ($tmp, $i, %argv, $mac_t) ; foreach my $v (@arg) { $tmp = '$ARG' . ++$i . '$' ; $argv{$tmp} = $v ; } $argv{'$HOSTADDRESS$'} = $cfg_host{$host}->{'address'} ; my $cmd_line = $cfg_cmd{$command}->{'command_line'} ; # search and replace foreach my $mac (keys %cfg_res) { $cmd_line =~ s/\Q$mac/$cfg_res{$mac}/g ; } foreach my $mac (keys %argv) { $cmd_line =~ s/\Q$mac/$argv{$mac}/g ; } return $cmd_line ; } ################################################################ # Command execution sub exec_cmd { my ($cmd) = @_ ; my $res = `$cmd` ; $res =~ s/\|.+// ; # if we use nsca $nsca_txt = $res ; my $exit_code = $? >> 8 ; $exit_code=($exit_code<0 or $exit_code>$#code_return)?$#code_return:$exit_code ; print " $host $serv $code_return[$?] $res\n" ; return $exit_code ; } use POSIX qw(O_WRONLY O_EXCL O_CREAT) ; ################################################################ # Send passive check result (it doesn't work for me...) sub send_passive_check { my ($host, $srv, $res) = @_ ; # warning about ssh test return 0 if ($res ne 0) ; my $file = $cfg_main{'command_file'} ; return 0 if ( ! -w $file ) ; my $t = localtime(time()) - 10 ; if (! open(CMD, ">$file")) { return 0 ; } print CMD "[$t] PROCESS_SERVICE_CHECK_RESULT;$host;$srv;$res;Test depuis la console" ; close(CMD) ; return 1 ; } ################################################################ # Send passive check result sub nsca_send_passive_check { my ($host, $srv, $res) = @_ ; # warning about ssh test # some checks can fail with apache user... return 0 if ($res ne 0) ; return 0 if (! -x $nsca_cmd) ; open(CMD, "|$nsca_cmd $nsca_arg") ; print CMD "$host\t$srv\t$res\t$nsca_txt\n" ; close(CMD) ; return 1 ; } ################################################################ # MAIN ################################################################ %cfg_main = process_cfg($cgi_cfg) ; process_objects(@{$cfg_main{'cfg_file'}}) ; %cfg_res = process_ressources($cfg_main{'resource_file'}) ; param() or die "Error with param() $!" ; print header() ; ################################################################ # check if user can use this script ################################################################ $user = remote_user() ; @tmp = grep (/^$user$/, split(/,/, $cfg_main{'authorized_for_system_commands'})) ; if (scalar(@tmp) == 0) { print "Sorry $user is not authorized\n" ; exit 0 ; } ################################################################ # cgi param auto-detection ################################################################ $host = param('host') ; $serv = param('service') ; $last_url = referer() ; $hostgrp = param('hostgroup') ; if ($last_url =~ /host=([^&]+)&?/) { $host = unescape($1) ; } if ($last_url =~ /service=([^&]+)&?/) { $serv = unescape($1) ; } # verfication $host =~ /^[0-9a-zA-Z_ \.-]+$/ or die "Error in $host format" ; if ($serv) { $serv =~ /^[0-9a-zA-Z_\.-]+$/ or die "Error in $serv format" ; } print " Nagios Host Test


" ; our $cmd ; if ($host and $serv) { $cmd = process_macro($host, $serv) ; if ($cmd) { my $res = exec_cmd($cmd) ; if ($cfg_main{'check_external_commands'}) { nsca_send_passive_check($host, $serv, $res) ; } } } elsif ($host) { foreach $serv (@{$cfg_hostsrv{$host}}) { $cmd = process_macro($host, $serv) ; my $res = exec_cmd($cmd) if ($cmd) ; if ($cfg_main{'check_external_commands'}) { nsca_send_passive_check($host, $serv, $res) ; } } } elsif ($hostgrp and $serv) { foreach $host (split(/,/, $cfg_hostgrp{$hostgrp}->{'members'})) { $cmd = process_macro($host, $serv) ; print $cmd ; } } print "
Host  Service  Status  Status Information


Retour" ; ################################################################ # Exemple of data access ################################################################ # display services # foreach $t (keys %cfg_srv) # { # print $t, values %{$cfg_srv{$t}}, "\n" ; # foreach $x (keys %{$cfg_srv{$t}}) { # print "---> [$x] {$t} (", $cfg_srv{$t}->{$x}, ")\n"; # } # } # display commands # foreach $t (keys %cfg_cmd) # { # foreach $x (keys %{$cfg_cmd{$t}}) { # print "---> $x $t ", $cfg_cmd{$t}{$x}, "\n"; # } # } # display ressources # foreach $t (keys %cfg_res) # { # print "$t => $cfg_res{$t}\n" ; # } # to dump graphics # foreach my $h (split(/,/, $cfg_hostgrp{'internet'}->{'members'})) { # foreach my $s (@{$cfg_hostsrv{$h}}) { # print "wget -O $h-$s.png --http-user=nagios --http-passwd=pwd 'http://nagios/nagios/cgi-bin/histogram.cgi?createimage&t1=1049148000&t2=1054072800&host=$h&service=$s&breakdown=dayofmonth&assumestateretention=yes&initialstateslogged=no&newstatesonly=no&graphevents=120&graphstatetypes=3'\n" ; # } # }