[PerlChina] 写了一个维护 apache prefork 模式下工作的脚本,希望大家多给点建议

Zhu Zhu zhuzhu at perlchina.org
Wed Mar 19 22:51:12 PDT 2008


检查APACHE是否工作以及负载,否则启动或者重新启动,
检查是否有过高CPU占用的进程,检查是否进程超过一定时间,并杀死符合条件的 
进程。


#!/usr/bin/perl
# zhuzhu at perlchina.org
# $Id: web_check.pl 109 2008-03-18 09:36:19Z fred1982 $
#
use strict;
use warnings;
use Proc::ProcessTable;
use DBI;
use Sys::Syslog;

# apache pid file location
my $serverIp = "125.0.0.1";   # <------------------- need set
my $pidfile = "/usr/local/apache2/logs/httpd.pid"; # <-- need set
my $ctlApache = "/usr/local/apache2/bin/apachectl"; # <- need set
my $isRunApache = 1;
my $waitApacheStartTime = 60;
my $waitLoopTime = 30;
my $apacheUid = 99;               # <------------------- need set
my $maxCpuUse = 15;
my $maxRuntime = 1800;
my $dbhost = '192.168.1.2';      # <------------------- need set
my $dbuser = 'monitor';
my $dbpassword = 'monitor_db';
my $dbname = 'monitor';
my $procName = 'httpd';
my $minApacheProcNum = 3;

# work loop block
while ("true") {
    my $nowLoadavg =  CheckLoadavg();
    # check apache pid
    if ($nowLoadavg > 30 && $isRunApache == 1) {
        while (checkApacheRun() == 0){
            system("$ctlApache stop");
            logRecord('server', $serverIp, '0');
            while("true"){
                sleep(5);
                my $httpdNum = &checkProcNum($procName);
                last if($httpdNum == 0);
            }
        }
        $isRunApache = 0;
    }
    
    if ($isRunApache == 0 || checkApacheRun() == -1){
        system("$ctlApache start");
        logRecord('server', $serverIp, '1');
        $isRunApache =1;
        sleep($waitApacheStartTime);
    }

    # clean bad apache processes
    my ($t) = new Proc::ProcessTable;
    my $killedProcNum = 0;
    foreach my $p (@{$t->table}){
        if ($p->uid eq $apacheUid){
            if($p->fname eq $procName && ($p->pctcpu > $maxCpuUse ||
                (time() - $p->start) > $maxRuntime)){
                $p->kill(9);
                $killedProcNum++;
            }
        }
    }
    if ($killedProcNum > 0) {
        logRecord('proc', $serverIp, $killedProcNum);
    }

    sleep($waitLoopTime);
}

#
# functions
#
sub checkApacheRun {
    my $pid = "";
    my $status = "";
    if (-e $pidfile) {
        $pid = `/bin/cat $pidfile`;
        $pid =~ s/\n//g;
        if($pid eq "") {
            return -1;
        }else{
            $status = &checkProcNum($procName, $minApacheProcNum);
            if ( $status < $minApacheProcNum ) { return -1; } else { 
return 0; }
        }
    }else{
        return -1;
    }
}

sub CheckLoadavg {
    my @avg = split(/ /, `cat /proc/loadavg`);
    return $avg[0];
}

sub logRecord {
    my ($type, $serverIp, $status) = @_;
    my $dbh = 
DBI->connect("dbi:mysql:$dbname:$dbhost",$dbuser,$dbpassword);
    if ($dbh){
        my $runTime = checkDateTime();
        if ($type eq "server")    {
            $dbh->do(qq{INSERT INTO `web_server_status` (server_ip, 
status, created) VALUES ('$serverIp', '$status', 'checkDateTime()')});
        } elsif ($type eq 'proc'){
            $dbh->do(qq{INSERT INTO `web_proc_status` (server_ip, 
killed_num, created) VALUES ('$serverIp', '$status', '$runTime')});
        } else {
            exit 0;
        }
        $dbh->disconnect();
    }else{
        openlog($0, 'cons,pid', 'user');
        syslog('info', "Connection Error: $DBI::errstr");
        closelog();
    }
}

sub checkDateTime {
    my ($s, $mm, $h, $d, $m, $y) = (localtime) [0,1,2,3,4,5];
    $m++;
    $y+=1900;
    if ($m<10) { $m = "0".$m; }
    if ($d<10) { $d = "0".$d; }
    if ($s<10) { $s = "0".$s; }
    if ($mm<10) { $mm = "0".$mm; }
    if ($h<10) { $h = "0".$h; }
    my $mysqlDateTime = "$y-$m-$d $h:$mm:$s";
    return $mysqlDateTime;
}

sub checkProcNum {
    my ($procName, $status) = @_;
    my $tp = new Proc::ProcessTable;
    my $procNum = 0;
    foreach my $proc ( @{$tp->table} ){
        if ($proc->fname eq $procName ) {
            $procNum++;
            last if ($status && $procNum > $status);
        }
    }
    return $procNum;
}



More information about the China-pm mailing list