Code Example

Home SourceForge Page freshmeat Page Download News Code Example Log Entries RTFM Change Log Extras E-mail


Below is the complete code of one of the programs that is included in the checksuite package. I try to follow 2 ideas...

keep it clean && keep it simple


#!/usr/bin/perl -w
########################################################
# Load Monitor by Larry Long - larry@djslyde.com       #
# checkload - 4/9 programs in checksuite v3.0          #
#                                                      #
# This greps the 5 minute load from /proc/loadavg      #
# and if it goes over a certain threshold, it can log  #
# and/or e-mail a notification.                        #
########################################################
use strict;
use Getopt::Std;
use Net::SMTP;

$ENV{'PATH'} = '/bin:/usr/bin:/usr/local/bin:/sbin:/usr/sbin:/usr/local/sbin';

# Options: -h (help) -l (log) -o (output to screen) -e (email) -p (pager)
my %opt;getopts('hlot:e:p:', \%opt);
usage_info() unless defined @ARGV;
usage_info() if exists $opt{h};

# Localize variables throughout the rest of the program
my($email,$host,$threshold,@ps_data,$plist,@load,$proc,$pid,@note,$notify,$logdate,$logfile,$logsnip,$script,$subject,@pnote,$pmail,$psubject);

# Are we root?
if($> != 0)
  {
  print STDERR "\n$0: This program HAS to be ran as root!!!\n\nPlease su to root
 or use 'sudo $0'!\n";
  exit 2;
  }

# Define variables
$threshold = $opt{t};$threshold = '7' unless defined $opt{t};
$email = $opt{e};$email = 'root@localhost' unless defined $opt{e};
$pmail = $opt{p};
$host = `hostname`;
$logfile = "/var/log/checksuite.d/checkload";
$logdate = `date '+%m/%d/%Y %H:%M:%S' `;
$script = " - [checksuite] checkload\n";
$logsnip = "----\n";
$notify = 0;
$subject = "[checksuite] advisory - load average is high on $host";
$psubject = "[checksuite] checkload";
chomp $host;chomp $logdate;chomp $subject;chomp $psubject;

# Pull the 5 minute load
push(@note, "[checksuite]\n[checkload]\n\n");
open(LOAD5, "/proc/loadavg") or die "Can't open /proc/loadavg!\n";
while()
   {
   @load = split(/\s+/, $_);
   my $defload = 0;
   my $sload = $defload + $load[1];chomp $sload;
   if($sload ge $threshold)
      {
      push(@note, "Current 5 minute load average is above threshold ($threshold): $sload\n\n");
      push(@pnote, "Load average is $sload\n");
      push(@note, "Possible Contributions:\n");

# Let's single out the processes that are contributing to the load
      open(PSLIST, "ps -elf --no-headers|");
      while()
         {
         chop;
         @ps_data = split(/\s+/, $_);
         if($ps_data[5] != 0)
            {
            $ps_data[15] = " " unless defined $ps_data[15];
            $ps_data[16] = " " unless defined $ps_data[16];
            $ps_data[17] = " " unless defined $ps_data[17];
            $ps_data[18] = " " unless defined $ps_data[18];
            $ps_data[19] = " " unless defined $ps_data[19];
            $ps_data[20] = " " unless defined $ps_data[20];
            $ps_data[21] = " " unless defined $ps_data[21];
            push(@note, "pid: $ps_data[9] |cpu time: $ps_data[5] |user: $ps_data[2] |command: $ps_data[14] $ps_data[15] $ps_data[16] $ps_data[17] $ps_data[18] $ps_data[19] $ps_data[20] $ps_data[21]\n");
            }
         }
      close(PSLIST);
      $notify++;
      }
   }
close(LOAD5);

# Define where the output goes
if($notify > 0)
   {
   log_data() if exists $opt{l};
   email_data() if exists $opt{e};
   screen_data() if exists $opt{o};
   pager_data() if exists $opt{p};
   }

# Subroutines
sub usage_info
   {
   my $usage = "
Usage: $0 [-h | -lo] [-t ] [-e ] [-p ]
Options:
-h              display this help
-l              log the output to /var/log/checksuite.d/checkload
-o              force output to screen
-t              sets the threshold for notification
-e              e-mail the output to a specified e-mail address
-p              send shortened output to a pager or cell phone
Where:
     threshold value - default is 7
         e-mail address of the recipient of the notification
                default is 'root'
\n";
   die $usage;
   }

sub log_data
   {
   open(LOG, ">>$logfile") or die "Can't open logfile!\n";
   print LOG $logdate,$script,@note,$logsnip;
   close(LOG);
   }

sub screen_data
   {
   print STDERR @note;
   }

sub email_data
   {
   my $smtp = Net::SMTP->new($host);
   if(! ref($smtp))
      {
      log_die("Cannot connect to SMTP\n");
      }
   $smtp->mail($email);
   $smtp->to($email);
   $smtp->data();
   $smtp->datasend("To: " . $email . "\n");
   $smtp->datasend("From: Checksuite Notification \n");
   $smtp->datasend("Return-Path: " . $email. "\n");
   $smtp->datasend("Subject: " . $subject . "\n");
   $smtp->datasend("\n");
   $smtp->datasend(@note);
   $smtp->datasend();
   $smtp->quit();
   }

sub pager_data
   {
   my $smtp = Net::SMTP->new($host);
   if(! ref($smtp))
      {
      log_die("Cannot connect to SMTP\n");
      }
   $smtp->mail($pmail);
   $smtp->to($pmail);
   $smtp->data();
   $smtp->datasend("To: " . $pmail . "\n");
   $smtp->datasend("From: Checksuite Notification \n");
   $smtp->datasend("Return-Path: " . $pmail. "\n");
   $smtp->datasend("Subject: " . $psubject . "\n");
   $smtp->datasend("\n");
   $smtp->datasend(@pnote);
   $smtp->datasend();
   $smtp->quit();
   }