#!/usr/bin/perl # # Force immediate service checks of services that match a perl regular # expression pattern # # $Header: /opt/home/doke/work/nagios/RCS/immediately_check_matching,v 1.8 2014/08/08 20:43:45 doke Exp $ my $statusfile = "/usr/local/nagios/var/status.dat"; my $cmdfile = "/usr/local/nagios/var/rw/nagios.cmd"; use strict; use warnings; use Getopt::Long; my( $verbose, $help, $noop, $pattern, $problem, $pending, %services_by_host, $ago ); $pattern = undef; $problem = 0; $pending = 0; $noop = 0; $verbose = 0; $help = 0; $ago = 20; # how far in the past to schedule the check, to deal with service latency, in minutes sub usage { my( $rc ) = @_; print qq{Usage: $0 [-renvh] -p Search for services matching perl regular expression pattern, and schedule a forced immediate service check for $ago minutes ago. Will not try to force a check for services that are only passively checked, ie ping or nessus. -p pattern search Pattern This is compared with each 'host/service', ignoring case. examples: 'mahler/prtdiag' to check prtdiag service on mahler 'copland' to check every service on copland 'sw-ne37-.*' to check every service on every computing center switch '/smf' to check smf service on every host '.' to immediately check everything (for use with -r or -e) -r only check services in a pRoblem state example: '$0 -r -p .' would re-check all service problems -e only check services in a pEnding state example: '$0 -e -p .' would force-check all pending services -n No-operation, don't actually schedule checks, but show matches, useful for testing your pattern. -v verbose -h this help \n}; exit $rc; } Getopt::Long::Configure ("bundling"); GetOptions( 'p=s' => \$pattern, 'r' => \$problem, 'e' => \$pending, 'n' => \$noop, 'v+' => \$verbose, 'h' => \$help, ); &usage( 0 ) if ( $help ); &usage( 1 ) if ( ! $pattern ); read_statusfile( $pattern ); check_services( $pattern ); exit 0; ########################## sub read_statusfile { my( $pattern ) = @_; my( $in_host, $in_service, $host, $service, $current_state, $state_type, $active_checks_enabled, $last_check, $next_check, $has_been_checked ); open( fH, $statusfile ) || die "can't read-open $statusfile: $!\n"; while ( ) { if ( ! $in_service && m/^(service|servicestatus)\s*{/ ) # } make vi happy { $in_service = 1; $host = undef; $service = undef; $current_state = 0; $state_type = 0; $active_checks_enabled = 0; $last_check = 0; $next_check = 0; $has_been_checked = 0; } elsif ( $in_service ) { if ( m/^\s*host_name=(.*)/ ) { $host = $1; } elsif ( m/^\s*service_description=(.*)/ ) { $service = $1; } elsif ( m/^\s*current_state=(\d+)/ ) { $current_state = $1; } elsif ( m/^\s*state_type=(\d+)/ ) { $state_type = $1; } elsif ( m/^\s*active_checks_enabled=(\d+)/ ) { $active_checks_enabled = $1; } elsif ( m/^\s*last_check=(\d+)/ ) { $last_check = $1; } elsif ( m/^\s*next_check=(\d+)/ ) { $next_check = $1; } elsif ( m/^\s*has_been_checked=(\d+)/ ) { $has_been_checked = $1; } # { make vi happy elsif ( m/^\s*}\s*$/ ) { $verbose > 1 && print "close curly brace: $host/$service $active_checks_enabled\n"; if ( ( $host =~ m/$pattern/i || $service =~ m/$pattern/i || "$host/$service" =~ m/$pattern/i ) && $active_checks_enabled ) { next if ( $problem && $current_state == 0 ); next if ( $pending && ( $has_been_checked || $last_check || ! $next_check ) ); $verbose && print "found $host/$service\n"; $services_by_host{ $host }{ $service } = [ $current_state, $state_type, $last_check, $next_check, $has_been_checked ]; } $in_service = 0; $host = undef; $service = undef; $current_state = 0; $state_type = 0; $active_checks_enabled = 0; $last_check = 0; $next_check = 0; $has_been_checked = 0; } } } close fH; } sub check_services { my( $pattern ) = @_; my( $now, $when, $author, $host, $service, $nagios_cmd, $current_state, $state_type, $active_checks_enabled, $last_check, $next_check, $has_been_checked ); $verbose && print "forcing service checks\n"; if ( scalar( keys %services_by_host ) < 1 ) { $verbose && print "no matching services\n"; return; } # append results to nagios command file if ( ! -p $cmdfile ) { die "cmdfile $cmdfile is not a pipe!\n"; } if ( ! open( cH, ">$cmdfile" ) ) { die "can't write-open cmdfile $cmdfile: $!\n"; } $now = time; $when = $now - $ago * 60; $author = getlogin || getpwuid( $< ) || 'unknown'; foreach $host ( sort keys %services_by_host ) { foreach $service ( sort keys %{$services_by_host{ $host }} ) { ( $current_state, $state_type, $last_check, $next_check, $has_been_checked ) = @{$services_by_host{ $host }{ $service }}; print "$host/$service\n"; $verbose && print " $current_state, $state_type, $last_check, $next_check, $has_been_checked\n"; if ( $next_check < $when ) { print " $host/$service already scheduled for ", scalar( localtime( $next_check ) ), "\n"; } #[] SCHEDULE_FORCED_SVC_CHECK;;; $nagios_cmd = sprintf "[%u] SCHEDULE_FORCED_SVC_CHECK;%s;%s;%u\n", $now, $host, $service, $when; $verbose && print "nagios_cmd = $nagios_cmd"; if ( ! $noop ) { print cH $nagios_cmd; } } } close cH; }