#!/usr/bin/perl
#
# system-health - report the system health via syslog/email
#
# 09/04/2003 - Russ W. Knize


################################################################################
# Configuration
################################################################################
$logTool = "/usr/bin/logger";
$logFac = "local4";
$raidTool = "/bin/cat /proc/mdstat";
$sensorTool = "/usr/bin/sensors";
$sensorChips = "lm79-isa-*";
$mailCmd = "/usr/bin/mail";
$mailUser = "root";
################################################################################


################################################################################
# printUsage
################################################################################
sub printUsage
{
    print <<END_PRINT_USAGE
usage: system-health [options]

options: -f       : generate full report (not just problems)
         -h       : print this message
         -l=facil : send output to syslog (local4 used if facility unspecified)
         -m=user  : send output to 'user' via email (root if unspecified)
         -r       : report RAID health
         -s       : report sensors health
         -v       : enable verbose output

If the -l and/or -m options are not specified, output is sent to stdout.
END_PRINT_USAGE
}


################################################################################
# printMsg() - print an message if in verbose mode
################################################################################
sub printMsg
{
    if ($verbose) { print "$_[0]"; }
}


################################################################################
# printDbg() - print an message if in verbose mode
################################################################################
sub printDbg
{
#    print "$_[0]";
}


################################################################################
# printError() - print an error to STDERR
################################################################################
sub printError
{
    print STDERR "ERROR: $_[0]\n";
}


################################################################################
# exitError() - print an error and exit
################################################################################
sub exitError
{
    print STDERR "ERROR: $_[0]\n";
    exit 1;
}


################################################################################
# Send report to appropriate location
################################################################################
sub report
{
}


################################################################################
# Main
################################################################################

# Process command line options
$full = 0;
$syslog = "";
$mail = "";
$raid = 0;
$sensors = 0;
$verbose = 0;
while ($ARGV[0] =~ /^-[a-zA-Z].*/)
{
    ($opt, $arg) = split /=|\n/, $ARGV[0], 2;
    if ($opt =~ /f/) { $full = 1; }
    if ($opt =~ /h/) { printUsage(); exit; }
    if ($opt =~ /l/) { if ($arg) { $syslog = $arg } else { $syslog = $logFac; }}
    if ($opt =~ /m/) { if ($arg) { $mail = $arg; } else { $mail = $mailUser; }}
    if ($opt =~ /r/) { $raid = 1; }
    if ($opt =~ /s/) { $sensors = 1; }
    if ($opt =~ /v/) { $verbose = 1; }
    shift @ARGV;
}

$report = "";

if ($raid)
{
    open(RAID, "$raidTool |") or exitError "failed reading RAID data";
    if ($full)
    {
        read(RAID, $raid, 10240);
        $report .= "\nSystem RAID:\n\n";
        $report .= "$raid\n";
    }
    else
    {
    $line = <RAID>;
    until ($line eq "")
    {
        $line =~ s/\n//;
        if ($line =~ /^(md\d+)\s*:\s*(.*)/)
        {
            $device = $1;
            $config = $2;
            $line = <RAID>;
            $line =~ s/^\s+|\n//;
            $line =~ /^(\d+)\s*blocks\s+level\s*(\d+),\s*(\S+)\D*(\d+)\s*\[(\d+)\/(\d+)\]\s*\[(\S+)\]/;
            if ($line =~ /^(\d+)\s*blocks\s+level\s*(\d+),\s*(\S+)\D*(\d+)\s*\[(\d+)\/(\d+)\]\s*\[(\S+)\]/)
            {
            	$blocks = $1;
            	$level = $2;
            	$chunk = $3;
            	$algo = $4;
            	$disks = $5;
            	$active = $6;
            	$states = $7;
            	
            	if ($states =~ /[^U]/ || $active != $disks)
            	{
            	    $report .= "\nSystem RAID:\n\n";
            	    $report .= "$device: $config\n";
            	    $report .= "     $blocks blocks, $chunk chunks, $disks disks, $active active, [$states]\n\n";
            	}
            }
        }
        
        $line = <RAID>;
    }
    }
    close(RAID);
}

if ($sensors)
{
    if ($full)
    {
        $sensors = "$sensorTool $sensorChips";
    }
    else
    {
        $sensors = "$sensorTool $sensorChips | grep ALARM";
    }
    
    open(SENSORS, "$sensors |") or exitError "failed reading sensor data";
    read(SENSORS, $sensors, 10240);
    close(SENSORS);
    
    if ($sensors)
    {
        $report .= "\nSystem sensors:\n\n";
        $report .= "$sensors\n";
    }
}

if ($report)
{
    if ($full)
    {
        $subject = "System health report";
        $logPri = "$syslog.info";
    }
    else
    {
        $subject = "System health ALARM!";
        $logPri = "$syslog.crit";
    }
        
    if ($mail)
    {
        open(MAIL, "| $mailCmd -s \"$subject\" $mailUser") or exitError "unable to pipe to mail";
        print(MAIL "$report");
        close(MAIL);
    }
    if ($syslog)
    {
        system("$logTool -p $logPri \"$subject\"");
        @lines = split /\n/, $report;
        do
        {
            $line = shift @lines;
            $line =~ s/\n//;
            if ($line) { system("$logTool -p $logPri \"$line\""); }    
        } while (@lines > 0)
    }
    if (!$mail && !$syslog)
    {
    	uc($subject);
    	print "\n*** $subject ***\n";
    	print "$report";
    }
}
