Code Example
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();
}