#!/usr/bin/perl # server_status_check.pl # Andrew Clegg # # This script parses the output of status.php and compares it to a # list of minimum and maximum allowable values for server resources # specified in a config file. The config file contains one rule per # line, like so: # # min MemFree 7500000 # min Usage_/LINUX/local64 95 # max LoadAverage5 0.1 # # Any line not in this format causes an error. Do not include any # percent signs, units (e.g. kB) etc. in the config file; these # are automatically stripped out from the results of status.php # before applying the rules. # # For each resource that is lower than a min value or larger than # a max value, a warning is printed. Also, if the config file # contains any rules which name resources that are not found in # the output of status.php at all, a warning is printed for each. # # It returns 0 if everything is fine, 255 if an error occurred, or # the number of warnings issued if one or more of the resource # rules are violated. use warnings; use strict; use LWP::Simple; @ARGV == 2 or die "Usage: server_status_check.pl \n"; open( CONFIG, $ARGV[ 1 ] ) or die "Cannot open config file: $!\n"; # Hashes to hold the min and max rules my( %minima, %maxima ); # Parse config file while( defined( my $rule = ) ) { # Ignore whitespace-only lines if( $rule =~ /\S+/ ) { my @fields = split( /\s+/, $rule ); if( @fields != 3 ) { die "Unparseable line in config file: $rule"; } my( $directive, $key, $val ) = @fields; $directive = lc( $directive ); if( $directive eq 'min' ) { if( exists $minima{ $key } ) { die "Duplicate minimum rule for resource $key\n"; } $minima{ $key } = $val; } elsif( $directive eq 'max' ) { if( exists $maxima{ $key } ) { die "Duplicate maximum rule for resource $key\n"; } $maxima{ $key } = $val; } else { die "Directive must be 'min' or 'max' in line: $rule"; } } } # URL where status.php is installed my $status_url = $ARGV[ 0 ]; # Attempt to read status from URL my $content = get $status_url; die "Could not read from $status_url\n" unless $content; # Loop through the status messages to parse them into %vars my %vars; foreach my $line ( split( "\n", $content ) ) { # Split messages on colon my( $key, $val ) = split( /:\s+/, $line ); # Trim off any trailing letters (i.e. kB), % signs or whitespace $val =~ s/[A-Za-z%\s]+$//; if( exists $vars{ $key } ) { warn "Duplicate value for key $key in server response\n"; } else { $vars{ $key } = $val; } # print "$key => $val\n"; } my $err_count = 0; my %missing_keys; # Loop through minima, looking for problems foreach my $key ( keys %minima ) { if( exists $vars{ $key } ) { my $cur_val = $vars{ $key }; my $min_val = $minima{ $key }; if( $cur_val < $min_val ) { warn "$key has value $cur_val which is less than minimum $min_val\n"; $err_count++; } } else { $missing_keys{ $key } = 1; } } # Loop through maxima, looking for problems foreach my $key ( keys %maxima ) { if( exists $vars{ $key } ) { my $cur_val = $vars{ $key }; my $max_val = $maxima{ $key }; if( $cur_val > $max_val ) { warn "$key has value $cur_val which is greater than maximum $max_val\n"; $err_count++; } } else { $missing_keys{ $key } = 1; } } # Report all missing keys too foreach my $key ( keys %missing_keys ) { warn "$key not found in server status report\n"; $err_count++; } # Exit with number of problems as return code exit $err_count;