[prev in list] [next in list] [prev in thread] [next in thread]
List: sidewinder
Subject: Re: [Sidewinder] script for moitoring processes on the Sidewinder
From: sidewinder-admin () adeptech ! com
Date: 2003-12-16 6:59:00
[Download RAW message or body]
i've attached a perl script that will check the cpu utilization of processes (using \
"ps auxww") every 60 seconds, calculate an average, and generate a report every 5 \
checks (5 minutes). this particular script does not currently "daemonize" itself so \
if you chose to use it, you'll probably want to run it with the proper output \
redirection. here is a bourne shell example:
./ps-check.pl > /var/log/ps-check.log 2>&1 &
some other notes/comments:
- it is *not* meant to be run out of cron; it is supposed to run continuously by \
itself.
- be sure to change the e-mail addressez and modify the cpu utilization threshold in \
the global_hash section near the top of the script.
- i cut this out of a more elaborate distributed monitoring script, so forgive the \
leftover complexity and lack of comments within the code.
i hope this helps someone!
randy blahut
rblahut@aol.com
In a message dated 12/11/2003 9:50:28 AM Eastern Standard Time, \
sidewinder-admin@adeptech.com writes:
> I have been trying to create a perl script for monitoring processes on the \
> Sidewinder. I wanted to have it send an e-mail for any process that exceed X% CPU \
> and I was going to run it from crontab every 5 minutes. My perl skills are sadly \
> lacking so I was wondering if anyone has already written a script that does that or \
> something similar. If it is a shell script or awk script that would be fine too. \
> I can stumble my way through modifying those without hurting my brain too badly =) \
> Also, does anyone know of a good site on the Internet for perl or awk systems \
> administration scripts?
> Regards,
> Jeffery Gieser
["ps-check.pl" (application/octet-stream)]
#!/usr/bin/perl
$stdin = *STDIN;
$stdout = *STDOUT;
$stderr = *STDERR;
$eol = "\n";
$tab = "\t";
$ERROR_STRING = '';
$VERSION = '1.0.0';
%global_hash = (
'ps_cmd' => 'ps auxww',
'mail_cmd' => 'mail',
'mail_subj' => 'process cpu utilization exceeded threshold',
'mail_to' => [
'root',
'admin@somewhere.com', # add e-mail addressez here as necessary
],
'thresh' => 80, # cpu utilization threshold
'check_t' => 60, # interval of secondz bewteen checkz
'max_hist' => 5, # intervalz before report
);
$global_hash{'report_t'} = $global_hash{'max_hist'};
# signalz
$SIG{'INT'} = \&handle_signals;
$SIG{'CHILD'} = \&handle_signals;
$SIG{'TERM'} = \&handle_signals;
$SIG{'PIPE'} = \&handle_signals;
#$SIG{'PIPE'} = IGNORE;
# main
do {
&error_exit;
} unless (&check_loop (\%global_hash));
&clean_exit;
# subroutinez
sub check_loop {
my ($config_hashref) = shift (@_);
my ($run_flag) = 1;
my ($check_count) = 0;
my (%data_hash) = ();
my (
$pid,
);
while ($run_flag) {
$check_count ++;
do {
return (0);
} unless (
&check_ps (
$config_hashref->{'ps_cmd'},
\%data_hash,
$config_hashref->{'thresh'},
$config_hashref->{'max_hist'},
)
);
if ($check_count == $config_hashref->{'report_t'}) {
# report on processez that exceeded thresholdz
do {
return (0);
} unless (
&mail_report (
$config_hashref,
\%data_hash,
)
);
$check_count = 0;
}
sleep ($config_hashref->{'check_t'});
}
return (1);
}
sub mail_report {
my ($config_hashref) = shift (@_);
my ($hashref) = shift (@_);
my (@pids) = sort { $a <=> $b } (keys (%{$hashref}));
my ($mail_pipe) = join (
'',
'| ',
$config_hashref->{'mail_cmd'},
' -s \'',
$config_hashref->{'mail_subj'},
': ',
scalar (localtime (time)),
'\' ',
join (' ', @{$config_hashref->{'mail_to'}}),
);
my (
$pid,
);
# return immediately if there is nothing to report
do {
return (1);
} unless (scalar (@pids));
do {
$ERROR_STRING = join ('', 'could not execute ', $config_hashref->{'mail_cmd'}, ': ', $!);
return (0);
} unless (open (MAIL, $mail_pipe));
print MAIL join (
$tab,
'pid',
'name',
'cpu-average',
), $eol;
foreach $pid (@pids) {
print MAIL join (
$tab,
$pid,
$hashref->{$pid}{'name'},
$hashref->{$pid}{'avg_cpu'},
), $eol;
}
close (MAIL);
return (1);
}
sub check_ps {
my ($cmd) = shift (@_);
my ($hashref) = shift (@_);
my ($thresh) = shift (@_);
my ($max_hist) = shift (@_);
my (%ps_hash) = ();
my (
$pid,
);
do {
return (0);
} unless (&parse_ps ($cmd, \%ps_hash));
foreach $pid (keys (%ps_hash)) {
# skip kernel idle thread (not applicable on sidewinder 5.2.1.x)
next if ($ps_hash{$pid}{'name'} =~ /^\(?idle\)?$/o);
if ($ps_hash{$pid}{'cpu'} >= $thresh) {
# create new hash structure as necessary
do {
$hashref->{$pid} = {
'name' => $ps_hash{$pid}{'name'},
'avg_cpu' => 0,
'hist' => [],
};
} unless (defined ($hashref->{$pid}));
# add history
push (@{$hashref->{$pid}{'hist'}}, $ps_hash{$pid});
# remove old history
if ((scalar (@{$hashref->{$pid}{'hist'}})) > $max_hist) {
shift (@{$hashref->{$pid}{'hist'}});
}
# calculate cpu average
&calc_avg (
$hashref->{$pid}{'hist'},
'cpu',
\$hashref->{$pid}{'avg_cpu'},
);
} else {
# remove pid from history if average is below threshold
if (defined ($hashref->{$pid})) {
# calculate cpu average
&calc_avg (
$hashref->{$pid}{'hist'},
'cpu',
\$hashref->{$pid}{'avg_cpu'},
);
if ($hashref->{$pid}{'avg_cpu'} < $thresh) {
delete ($hashref->{$pid});
}
}
}
}
return (1);
}
sub calc_avg {
my ($arrayref) = shift (@_);
my ($key) = shift (@_);
my ($avg_ref) = shift (@_);
my ($total) = 0;
my (
$hashref,
);
foreach $hashref (@{$arrayref}) {
$total += $hashref->{$key};
}
${$avg_ref} = $total / scalar (@{$arrayref});
return (1);
}
sub parse_ps {
my ($cmd) = shift (@_);
my ($hashref) = shift (@_);
my (@parts) = ();
my (
$output,
$base,
);
do {
$ERROR_STRING = join ('', 'could not execute ', $cmd, ': ', $!);
return (0);
} unless ($output = `$cmd`);
foreach $line (split ($eol, $output)) {
next if ($line =~ /^\s*USER/o);
(@parts) = split (/\s+/, $line);
next unless ((scalar (@parts)) >= 9);
$base = $parts[10];
# attempt to strip certain charz from process name
$base =~ s/[\/\(\[]?([\w\-\.]+)[:\)\]]?$/$1/o;
%{$hashref->{$parts[1]}} = (
'cpu' => $parts[2],
'mem' => $parts[3],
'rss' => $parts[5],
'time' => $parts[9],
'name' => $base,
'cmd' => join (' ', @parts[10 .. $#parts]),
);
}
return (1);
}
# support routinez
sub log_message {
print $stderr join ('', @_), $eol;
return (1);
}
sub clean_exit {
my ($status) = shift (@_) || 0;
exit ($status);
}
sub error_exit {
my ($status) = shift (@_) || 1;
&log_message ($ERROR_STRING);
&clean_exit ($status);
}
sub handle_signals {
my ($signal) = shift (@_);
print $stderr 'received signal ', $signal, $eol;
&clean_exit;
}
# end
_______________________________________________
Sidewinder mailing list
Sidewinder@adeptech.com
http://mail.adeptech.com/mailman/listinfo/sidewinder
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic