no way to compare when less than two revisions
Differences
This shows you the differences between two versions of the page.
— | monitors:check-client [2010/08/23 22:23] (current) – created - external edit 127.0.0.1 | ||
---|---|---|---|
Line 1: | Line 1: | ||
+ | ====== client-check.pl ====== | ||
+ | |||
+ | ^ Author | [[ dbaldwin@users.sf.net | David Baldwin ]] | | ||
+ | ^ Compatibility | Xymon 4.2 | | ||
+ | ^ Requirements | Perl, [[monitors: | ||
+ | ^ Download | client-check.pl | | ||
+ | ^ Last Update | 2010-07-29 | | ||
+ | |||
+ | ===== Description ===== | ||
+ | |||
+ | ===== Installation ===== | ||
+ | === Client side === | ||
+ | |||
+ | === Server side === | ||
+ | |||
+ | client-check.pl and XymonExt.pm in $BBHOME/ext | ||
+ | |||
+ | ===== Source ===== | ||
+ | ==== client-check.pl ==== | ||
+ | |||
+ | <hidden onHidden=" | ||
+ | <code perl> | ||
+ | # | ||
+ | |||
+ | # | ||
+ | #* client-check.pl : Xymon client message processor. | ||
+ | #* */ | ||
+ | #* This perl program is a server-side module using the */ | ||
+ | #* data sent by the Xymon clients. This program is fed data from the */ | ||
+ | #* Xymon " | ||
+ | #* message is processed by looking at various sections and generates | ||
+ | #* a test status report when various conditions are met */ | ||
+ | #* */ | ||
+ | #* Original 2007-Jan-28 by Henrik Storner < | ||
+ | #* Modified 2008-2010 by David Baldwin < | ||
+ | #* */ | ||
+ | #* This program is in the public domain, and may be used freely for */ | ||
+ | #* creating your own Xymon server-side modules. | ||
+ | #* */ | ||
+ | # | ||
+ | # | ||
+ | # CONFIG START | ||
+ | |||
+ | # default route where other than .1 address on subnet | ||
+ | my %netCheckRoutes = ( prod => { net => " | ||
+ | ); | ||
+ | |||
+ | # check minimum available memory in host under [free] section | ||
+ | my %memCheckTable = ( esx => { host => " | ||
+ | ); | ||
+ | |||
+ | # CONFIG END | ||
+ | |||
+ | =pod | ||
+ | |||
+ | =head1 NAME | ||
+ | |||
+ | | ||
+ | |||
+ | =head1 SYNOPSIS | ||
+ | |||
+ | Install script in F< | ||
+ | |||
+ | Ensure you also have F< | ||
+ | |||
+ | Add following lines to F</ | ||
+ | |||
+ | | ||
+ | ENVFILE / | ||
+ | NEEDS hobbitd | ||
+ | CMD hobbitd_channel --channel=client --log=$BBSERVERLOGS/ | ||
+ | |||
+ | =head1 DESCRIPTION | ||
+ | |||
+ | Requires: C< | ||
+ | |||
+ | Requires: F< | ||
+ | |||
+ | See CONFIG section at top of script | ||
+ | |||
+ | =head1 TESTING | ||
+ | |||
+ | If you wish to add your own tests, this script can be run against current client report for that host | ||
+ | |||
+ | C<bbcmd client-check.pl -d MYHOST> | ||
+ | |||
+ | | ||
+ | DBG: using clientlog for MYHOST (1.1.1.2) | ||
+ | DBG: clientID linux (linux) | ||
+ | / | ||
+ | |||
+ | & | ||
+ | |||
+ | |||
+ | | ||
+ | " | ||
+ | |||
+ | DBG: netCheck MYHOST (1.1.1.1) GW: 1.1.0.10 SM: 0.0.0.0 | ||
+ | / | ||
+ | |||
+ | & | ||
+ | |||
+ | |||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | " | ||
+ | |||
+ | =cut | ||
+ | |||
+ | my $xymonlib; | ||
+ | BEGIN { $xymonlib = $ENV{BBHOME} && " | ||
+ | |||
+ | use strict; | ||
+ | use lib $xymonlib; | ||
+ | use XymonExt; | ||
+ | |||
+ | |||
+ | my $bb; | ||
+ | my $bbdisp; | ||
+ | |||
+ | my $hostname = ""; | ||
+ | my $clientip = ""; | ||
+ | my $clientname = ""; | ||
+ | my $clientos = ""; | ||
+ | my $msgtxt = ""; | ||
+ | my %sections = (); | ||
+ | my $cursection = ""; | ||
+ | |||
+ | my $debug=0; | ||
+ | my $ipsubre = qr/ | ||
+ | my $ipre = qr/ | ||
+ | $|=1; | ||
+ | |||
+ | # Get the BB and BBDISP environment settings. | ||
+ | $bb = $ENV{" | ||
+ | $bbdisp = $ENV{" | ||
+ | |||
+ | for(my $i=0; $i< | ||
+ | if($ARGV[$i] =~ / | ||
+ | $debug++; | ||
+ | } elsif($i=$# | ||
+ | $debug ||= 1; | ||
+ | $clientname=$ARGV[$i]; | ||
+ | } | ||
+ | } | ||
+ | |||
+ | |||
+ | if($clientname ne "" | ||
+ | open CL,"bb $bbdisp \' | ||
+ | $hostname = $clientname; | ||
+ | $clientip = XymonExt-> | ||
+ | warn "DBG: using clientlog for $hostname ($clientip)\n" | ||
+ | } else { | ||
+ | open CL,"/ | ||
+ | } | ||
+ | # Main routine. | ||
+ | # | ||
+ | # This reads client messages from <CL>, looking for the | ||
+ | # delimiters that separate each message, and also looking for the | ||
+ | # section markers that delimit each part of the client message. | ||
+ | # When a message is complete, the processmessage() subroutine | ||
+ | # is invoked. $msgtxt contains the complete message, and the | ||
+ | # %sections hash contains the individual sections of the client | ||
+ | # message. | ||
+ | |||
+ | while (my $line = <CL>) { | ||
+ | if ($line =~ / | ||
+ | # It's the start of a new client message - the header looks like this: | ||
+ | # @@client# | ||
+ | |||
+ | # Grab the hostname field from the header | ||
+ | my @hdrfields = split(/\|/, $line); | ||
+ | $hostname = $hdrfields[3]; | ||
+ | $hostname =~ s/,/./g; | ||
+ | XymonExt-> | ||
+ | $clientip = XymonExt-> | ||
+ | warn "DBG: processing $hostname ($clientip)\n" | ||
+ | |||
+ | # Clear the variables we use to store the message in | ||
+ | $msgtxt = ""; | ||
+ | %sections = (); | ||
+ | $cursection = ""; | ||
+ | $clientname = ""; | ||
+ | $clientos = ""; | ||
+ | } | ||
+ | elsif ($line =~ /^\@\@/) { | ||
+ | # End of a message. Do something with it. | ||
+ | runTests(); | ||
+ | } | ||
+ | elsif ($line =~ / | ||
+ | # Start of new message section. | ||
+ | |||
+ | $cursection = $1; | ||
+ | $sections{ $cursection } = " | ||
+ | } | ||
+ | elsif ($line =~ / | ||
+ | # client header - used when testing against current client report | ||
+ | # | ||
+ | # | ||
+ | |||
+ | $msgtxt .= $line; | ||
+ | |||
+ | $clientname = $1; | ||
+ | $clientos = $2; | ||
+ | warn "DBG: clientID $clientname ($clientos)\n" | ||
+ | } | ||
+ | else { | ||
+ | # Add another line to the entire message text variable, | ||
+ | # and the the current section. | ||
+ | $msgtxt .= $line; | ||
+ | if($cursection) { | ||
+ | $sections{ $cursection } .= $line; | ||
+ | } else { | ||
+ | my $time = scalar localtime; | ||
+ | warn "$time client-check: | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | # End of a message. Do something with it. Will only get here using clientlog (we hope) | ||
+ | runTests(); | ||
+ | |||
+ | sub runTests { | ||
+ | |||
+ | whoCheck(); | ||
+ | netCheck(); | ||
+ | memCheck(); | ||
+ | } | ||
+ | |||
+ | sub report { | ||
+ | |||
+ | my($hostname, | ||
+ | # Build the command we use to send a status to the Xymon daemon | ||
+ | |||
+ | if($debug) { | ||
+ | print "Would report: | ||
+ | } else { | ||
+ | # And send the message | ||
+ | | ||
+ | } | ||
+ | } | ||
+ | |||
+ | # This subroutine processes the client message. In this case, | ||
+ | # we watch the [who] section of the client message and alert | ||
+ | # if there is a root login active. | ||
+ | |||
+ | sub whoCheck { | ||
+ | my $color; | ||
+ | my $summary; | ||
+ | my $statusmsg; | ||
+ | my $sec = " | ||
+ | my $hobbitcolumn = " | ||
+ | |||
+ | # Dont do anything unless we have the " | ||
+ | return unless ( $sections{$sec} ); | ||
+ | |||
+ | # Is there a " | ||
+ | # Note that we must match with /m because there are multiple | ||
+ | # lines in the [who] section. | ||
+ | if ( $sections{$sec} =~ /^root /m ) { | ||
+ | $color = " | ||
+ | $summary = "ROOT login active"; | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | else { | ||
+ | $color = " | ||
+ | $summary = " | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | report($hostname, | ||
+ | } | ||
+ | |||
+ | # This subroutine processes the client message. In this case, | ||
+ | # we watch the [route] section of the client message and alert | ||
+ | # if the default route is incorrect | ||
+ | |||
+ | sub netCheck { | ||
+ | my $color; | ||
+ | my $summary; | ||
+ | my $statusmsg; | ||
+ | my $sec = " | ||
+ | my $hobbitcolumn = " | ||
+ | |||
+ | # Dont do anything unless we have the " | ||
+ | return unless ( $sections{$sec} ); | ||
+ | |||
+ | # Is there a default gateway somewhere in the " | ||
+ | # Note that we must match with /m because there are multiple | ||
+ | # lines | ||
+ | $color = " | ||
+ | $summary = " | ||
+ | $statusmsg = "& | ||
+ | #darwin form: | ||
+ | # default | ||
+ | # 1.1/ | ||
+ | # 1.1.0.1 | ||
+ | |||
+ | if ( $sections{$sec} =~ / | ||
+ | my $gw = ($clientname eq " | ||
+ | my $sm = ($clientname eq " | ||
+ | warn "DBG: netCheck $hostname ($clientip) GW: $gw SM: $sm\n" if $debug; | ||
+ | my $isok = 1; | ||
+ | my $found = 0; | ||
+ | foreach my $sn (keys %netCheckRoutes) { | ||
+ | my %snr = %{$netCheckRoutes{$sn}}; | ||
+ | warn "DBG: NET: $sn IP: $snr{net} GW: $snr{gw} SM: $snr{mask}\n" | ||
+ | if(! exists $snr{ipre}) { | ||
+ | my $netre = $snr{net}; | ||
+ | $netre =~ s/\./\\./g; | ||
+ | $netre =~ s/\.$//; | ||
+ | $netCheckRoutes{$sn}{ipre} = qr/ | ||
+ | } | ||
+ | if( $clientip =~ $netCheckRoutes{$sn}{ipre} ) { | ||
+ | $found = 1; | ||
+ | $isok = $gw eq $snr{gw}; | ||
+ | $summary = "Found defgw: $gw OK"; | ||
+ | last | ||
+ | } | ||
+ | } | ||
+ | if( !$found && $gw =~ / | ||
+ | my $net = $1; | ||
+ | warn "DBG: DEFAULT IP: $net GW: $gw SM: /24\n" if $debug; | ||
+ | $net =~ s/\./\\./g; | ||
+ | $isok = 0 unless $clientip =~ /^$net/; | ||
+ | $summary = "Found defgw: $gw OK" if $isok; | ||
+ | } | ||
+ | if(!$isok) { | ||
+ | $color = " | ||
+ | $summary = "Bad default route $gw for $clientip found"; | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | } else { | ||
+ | $color = " | ||
+ | $summary = " | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | |||
+ | report($hostname, | ||
+ | } | ||
+ | |||
+ | # This subroutine processes the client message. In this case, | ||
+ | # we watch the [free] section of the client message and alert | ||
+ | # if the machine is an ESX server and the physical memory size is not 800MB | ||
+ | |||
+ | sub memCheck { | ||
+ | my $color; | ||
+ | my $summary; | ||
+ | my $statusmsg; | ||
+ | my $sec = " | ||
+ | my $hobbitcolumn = " | ||
+ | my $min; | ||
+ | |||
+ | # Dont do anything unless we have the " | ||
+ | return unless ( $sections{$sec} ); | ||
+ | my $found = 0; | ||
+ | foreach my $mh (keys %memCheckTable) { | ||
+ | my %mhr = %{$memCheckTable{$mh}}; | ||
+ | warn "DBG: HOST: $mh MIN: $mhr{min}\n" | ||
+ | if(! exists $mhr{hostre}) { | ||
+ | my $hostre = $mhr{host}; | ||
+ | $memCheckTable{$mh}{hostre} = qr/ | ||
+ | } | ||
+ | $found = $hostname =~ $memCheckTable{$mh}{hostre}; | ||
+ | $min = $mhr{min}; | ||
+ | last if $found; | ||
+ | } | ||
+ | return unless ( $found ); | ||
+ | |||
+ | # Get the Mem: line | ||
+ | # Note that we must match with /m because there are multiple | ||
+ | # lines | ||
+ | $color = " | ||
+ | $summary = " | ||
+ | |||
+ | if ( $sections{$sec} =~ / | ||
+ | my $tot = $1; | ||
+ | $statusmsg = sprintf("& | ||
+ | warn "DBG: memCheck $hostname ($clientip) PhysMEM: $tot\n" | ||
+ | my $isok = $tot > $min; | ||
+ | if(!$isok) { | ||
+ | $color = " | ||
+ | $summary = sprintf(" | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | } else { | ||
+ | $color = " | ||
+ | $summary = " | ||
+ | $statusmsg = "& | ||
+ | } | ||
+ | |||
+ | report($hostname, | ||
+ | } | ||
+ | |||
+ | </ | ||
+ | </ | ||
+ | |||
+ | ===== Known Bugs and Issues ===== | ||
+ | |||
+ | ===== To Do ===== | ||
+ | |||
+ | ===== Credits ===== | ||
+ | |||
+ | original rootlogin.pl script from Henrik | ||
+ | |||
+ | ===== Changelog ===== | ||
+ | |||
+ | * **2010-07-29** | ||
+ | * Initial release | ||