#!/usr/bin/perl -w
use POSIX qw(setsid);
sub checkconfig;
sub daemonize;
sub usage;
# this should take a -C for a different config file at some point
%c=checkconfig("/etc/slicehostd.conf");
$| = 1;
daemonize;
open(OFP,">>".$c{'logfile'}) or die "couldn't open ".$c{'logfile'}." : $!";
$count=0;
while(1){
if($count > 0){ $count--; }
open(IFP,"/proc/loadavg") or die "$!";
$l=<IFP>;
close(IFP);
chomp($l);
$l=~s/ .*//;
(undef,$m,$h,$day,$mon,$yr)=localtime();
$mon++;
$yr+=1900;
$date=sprintf("%d-%02d-%02d %02d:%02d ",$yr, $mon, $day, $h,$m);
if($l > $c{'killload'} and $count == 0){
print OFP "$date load = $l WHOA! killing/restarting ".$c{'procs'}."\n";
foreach $p (split(/,/,$c{'procs'})){
system("killall -TERM $p");
}
sleep($c{'killsleep'});
foreach $p (split(/,/,$c{'procs'})){
system("/etc/init.d/$p restart");
}
$count=2;
}
elsif($l > $c{'restartload'} and $count == 0){
print OFP "$date load = $l restarting ".$c{'procs'}."\n";
foreach $p (split(/,/,$c{'procs'})){
system("/etc/init.d/$p restart");
}
$count=2;
}
sleep($c{'stdsleep'});
}
exit 0; # NOTREACHED
sub checkconfig {
my $line;
my %ret;
my $file=shift;
my $matched;
my @c=qw(logfile stdsleep killsleep killload restartload procs);
# sensible defaults for these things
$ret{'logfile'}="/var/log/slicehostd.log";
$ret{'stdsleep'}=60;
$ret{'killsleep'}=20;
$ret{'killload'}=10.0;
$ret{'restartload'}=3.0;
$ret{'procs'}="apache2,mysql";
open(IFP,$file) or die "couldn't open config file $file : $!";
while($line=<IFP>){
$line=~s/#.*//;
chomp $line;
if($line=~/^\s*$/){ next; }
$matched=0;
foreach $w (@c){
chomp $w;
if($line=~/^$w=/){
$ret{$w}=$line;
$ret{$w}=~s/.*=//;
$matched=1;
}
}
if(!$matched){
print STDERR "unknown config line $line\n";
}
}
close(IFP);
return %ret;
}
sub daemonize {
chdir '/' or die "Can't chdir to /: $!";
open STDIN, '/dev/null' or die "Can't read /dev/null: $!";
open STDOUT, '>>/dev/null' or die "Can't write to /dev/null: $!";
open STDERR, '>>/dev/null' or die "Can't write to /dev/null: $!";
defined(my $pid = fork) or die "Can't fork: $!";
exit if $pid;
setsid or die "Can't start a new session: $!";
umask 0;
}
sub usage {
print<<EOF;
slicehostd : daemon for running on a slicehost (or any low-RAM machine)
that restarts services when the load gets too high. Config file is in
/etc/slicehostd.conf by default. Config file should have comments in
it that explain what to do and how to do it.
Not quite finished; doesn't take any options yet. Sorry.
EOF
exit 1;
}