Remi Fasol wrote: > > hi Joshua, > > is this your recommended setup when using Apache::ASP > or is this for mod_perl in general? > mod_perl in general. > if it's for Apache::ASP, do you have a sample CPU > limit script and/or watchdog? > Check out Apache::Resource, the CPU limiting feature is well documented there. You need to install also BSD::Resource on your system. My watch dog code is a bit of a mess, but it uses LWP::*, or lwp-request to query the server, test for expected output, and if it takes too long restart the server. If too many subsequent restarts fail to work, and apache is still not responding in a timely manner, send an email to the administrator. Some code is posted below that you can adapt for you use. --Joshua _________________________________________________________________ Joshua Chamas Chamas Enterprises Inc. NODEWORKS >> free web link monitoring Huntington Beach, CA USA http://www.nodeworks.com 1-714-625-4051 ## main watchdog, you can add other testing modules, I test ## web server, database, dns, smtp with this. use Util; use My::UserAgent; # use LWP::Debug qw(+); my $ua = new My::UserAgent; my $self = new Util::Monitor; $self->add_run(bless { 'name' => 'proxy homepages test', # make sure both the secure and non-secure pages are working 'test' => sub { my $http_doc = $ua->Request('http://www.nodeworks.com'); my $https_doc = $ua->Request('https://www.nodeworks.com'); ($http_doc->{success} && $https_doc->{success}); }, # restart www server gracefully, works when server isn't started # all too 'fix' => sub { $self->log("attempting restart of www server"); `/usr/local/apache/sbin/apachectl graceful`; }, # allow for downtime of one - two minutes before sending page # it may take a minute to reboot server when the machine is busy 'period' => 30, 'max_tests' => 3, 'timeout' => 30, }, Util::Monitor::Run ); $self->monitor; ## from Util.pm package Util::Monitor; @ISA = qw(Util); use Class::Struct; use File::Basename; use Carp qw(confess cluck carp); use HTTP::Date; use Net::SMTP; use Net::Config; use Data::Dumper; use Tie::CPHash; use File::Basename; use Time::localtime; @Mandatory = ('name', 'test', 'period'); $MaxSleep = 60; $DefaultMaxTests = 3; unless(keys %Util::Monitor::Run::) { struct(Util::Monitor::Run => { 'name' => "\$", # string describing test 'test' => "\$", # CODE 'fix' => "\$", # CODE 'period' => "\$", # time in seconds to iterate 'max_tests' => "\$", # number of times before erroring 'num_tests' => "\$", # number of times before erroring 'last' => "\$", # time last ran 'timeout' => "\$", # timeout for test }); } sub new { chdir(File::Basename::dirname($0)) || die("can't change to dir for $0"); my $self = bless { runs => [] }; $self->write_pidfile; $self; } # add runs before monitoring sub add_run { my($self, $run) = @_; die("no run") unless $run; die("run is not well defined") unless (@Mandatory == grep(defined $run->{$_}, @Mandatory)); $run->max_tests || $run->max_tests($DefaultMaxTests); $run->last(0); $run->num_tests(0); push(@{$self->{runs}}, $run); } # main code to loop over sub monitor { my $self = shift; while($self->alive) { $self->do_runs; $self->sleep; } } sub sleep { my $self = shift; my $next_time = time() + $MaxSleep; for(@{$self->{runs}}) { my $run_time = $_->period + $_->last; if($run_time < $next_time) { $next_time = $run_time; } } my $sleep_time = $next_time - time; if($sleep_time > 0) { $self->log("sleeping $sleep_time"); sleep($sleep_time); } else { $sleep_time = 0; } $sleep_time; } sub do_runs { my $self = shift; @{$self->{runs}} > 0 or die("no runs to do"); my $run; for $run (@{$self->{runs}}) { my $run_time = $run->period + $run->last; next unless ($run_time <= time); $self->log("doing run name ".$run->name); $self->do_run($run); $run->last(time); } } sub do_run { my($self, $run) = @_; my $name = $run->name; my $start = time(); my $result = $self->try($run->test, $run->timeout); my $total = time - $start; $self->log("time for $name: $total"); if($result) { # test succeeded $self->log("test success for $name, result $result"); if($run->num_tests) { $self->sendmail({ Subject => $run->name . " fixed", Body => "failed times before fixing: ".$run->num_tests }); } $run->num_tests(0); $result; } else { $run->num_tests($run->num_tests + 1); $self->log("test fail for $name"); if($run->num_tests >= $run->max_tests) { $self->log("tests for $name failed, sending crit"); $self->critical("$name failed"); $run->num_tests(0); } if($run->fix) { if($self->try($run->fix, $run->timeout)) { $self->log("fix for $name success"); } else { $self->log("fix for $name failed"); } } 0; $run->last(time); } } sub alive { my $self = shift; $$ eq $self->read_pidfile; } sub pidfile { my($self, $name) = @_; $name ||= basename($0); $name =~ s/.[^.]+$//s; $name .= "_pid"; $name; } # pid_file is the name_pid file for the running process sub read_pidfile { my($self, $name) = @_; my $pidfile = $self->pidfile($name); local *PID; open(PID, $pidfile) || return ''; my $data = <PID>; close PID; $data || ''; } sub write_pidfile { my($self, $name) = @_; my $pidfile = $self->pidfile($name); local *PID; open(PID, ">$pidfile") || die("can't write $pidfile"); print PID $$; close PID; 1; } sub sendmail { my($self, $mail, %args) = @_; my($smtp, @to, $server); my($rv) = 1; tie %mail, 'Tie::CPHash'; %mail = %{$mail}; $mail = \%mail; $mail->{To} ||= $AdminEmail; $mail->{From} ||= $SystemEmail; confess("not enough args to send mail") unless ($mail->{to} && $mail->{body} && $mail->{subject} && $mail->{from}); # connect to server $args{Timeout} ||= $SmtpTimeout; if(exists $mail->{Debug}) { $args{Debug} = $mail->{Debug}; delete $mail->{Debug}; } $smtp = Net::SMTP->new(%args); $smtp || return(0); @to = (ref $mail->{to}) ? @{$mail->{to}} : ($mail->{to}); $smtp->mail($mail->{from}); $smtp->to(@to); my($data); my $body = $mail->{body}; delete $mail->{body}; my %done; for('Subject', 'From', 'Reply-To', 'Organization', 'To', keys %$mail) { next unless $mail->{$_}; next if $done{lc($_)}++; my $add = ref($mail->{$_}) ? join(", ", @{$mail->{$_}}) : $mail->{$_}; $data .= "$_: $add\n"; } $data .= "\n" . $body; $smtp->data($data) || ($rv = 0); $smtp->quit(); $rv; }