This script stops http, exim and cpanel, and chkservd if load average exceeds 8.
It stops http if load exceeds 6 but is less than 8.
If it stops anything it checks every 10 seconds to see how load drops until load drops below 3, then it restarts whatever it stopped.
It is a bit drastic, but has saved us from losing control of servers when a nasty script takes over or someone from the outside is pounding on the server. Our idea was to drop services before losing server control.
Place this in /usr/local/sbin and then add a line into the crontab (ie crontab -e to edit crontab).
*/3 * * * * /usr/local/sbin/cpumonster >>/var/log/cpumonster.log 2>&1
This is what I use. Use at your own risk. Improvements are welcome.
Code:
#!/usr/local/bin/perl
$deathlimit = 8.0;
$deathstop = 0;
$hardlimit = 6.0;
$softlimit = 3.0;
$timespan = 10;
$debug = 0;
$quiet = 0;
$load = getload();
if($load >= $hardlimit){
do{
track("load $load too hight!\n");
track("stopping apache!\n");
hookup("/sbin/service httpd stop");
hookup("/sbin/service httpd stop");
hookup("/sbin/service httpd stop");
if($load >= $deathlimit){
hookup("/sbin/service exim stop");
hookup("/sbin/service cpanel stop");
hookup("/sbin/service ftp stop");
hookup("/sbin/service chkservd stop");
track("deathstop stop\n");
$deathstop = 1;
}
track("sleep $timespan seconds...\n");
sleep($timespan);
$load = getload();
}while($load >= $softlimit);
track("load $load is okay!\n");
track("starting apache!\n");
hookup("/sbin/service httpd start");
if($deathstop){
track("deathstop start\n");
hookup("/sbin/service exim start");
hookup("/sbin/service cpanel start");
hookup("/sbin/service ftp start");
hookup("/sbin/service chkservd start");
}
exit(0);
}
else{
track("load $load is okay!\n");
exit(0);
}
sub getload{
my $what = `cat /proc/loadavg`;
chomp($what);
my @cells = split(/\s+/,$what);
chomp(@cells);
return($cells[0]);
}
sub track{
my $what = $_[0];
my $stamp = gettimestamp(time);
$quiet == 0 || return;
print "$stamp $what";
}
sub hookup{
my $cmd = $_[0];
track("$cmd\n");
if($debug == 0){
system($cmd);
}
}
sub gettimestamp{
my ($sec,$min,$hour,$mday,
$mon,$year,$wday,$yday,$isdst) =
localtime($_[0]);
return(sprintf("%04d-%02d-%02d %02d:%02d:%02d ",
1900+$year,$mon+1,$mday,$hour,$min,$sec));
}
Hope it helps!
ER