четверг, 18 декабря 2008 г.

Скрипт MySQL Watch

Довольно часто возникает такая ситуация, когда процесс MySQL грузит всю систему, а пока "залогинишся" на сервер, пройдет кучу времени, и нагрузка может уже упасть. По-этому сложно выловить пользователя злоупотребляющего MySQL ресурсами.

Для этого есть скрипт, код скрипта ниже. Вы должны запустить этот скрипт в фоновом режиме. Она свяжется с MySQL и будет оставатся на связи. Каждые 10 минут (по умолчанию), он будет проверять, чтобы убедиться, что пользователь не перешагнул планку нагрузки сервера. Вы можете изменить время / лимиты. Начиная с версии 0.2 скрипт обладает способностью убивать пользователськие подключения к MySQL, если они превышают установленный лимит. Все отчеты отправляются на емайл администратора.

#!/usr/bin/perl


# Version: 0.02 


 


use DBI();


use Sys::Hostname;


 


 


#Sets the maximum concurrent connections per MySQL user.


my $max_concurrent_connections        = '15';


 


#Who to tell about this user... (email)


my $warning_email            = 'noc@localhost';


 


#Kill Abuser's MySQL Connections (0 = no, 1 = yes)


my $kill_user                = '0';


 


#MySQL polling in seconds (600 = 10 minutes)


my $check_interval            = '600';


 


###################################


####NO NEED TO EDIT BELOW HERE#####


###################################


#Set these if you wish to run the script as a diffrent mysql user.


my $mysqluser                = '';


my $mysqlpass                = '';


 


$hostname = hostname();


if ((!$mysqluser) or (!$mysqlpass)) {


    open(MYCNF,"/root/.my.cnf");


    while(<MYCNF>) {


        chomp;


        s/"//g;


        if(/user/is) { (undef,$mysqluser) = split('=', $_, 2); }


        if(/pass/is) { (undef,$mysqlpass) = split('=', $_, 2); }


    }


    close(MYCNF);


}


 


my $dbh = DBI->connect("DBI:mysql:host=localhost", "$mysqluser", "$mysqlpass", {'RaiseError' => 1});


 


while(1) {


    unless ($dbh->ping) {


        $dbh->disconnect;


        $dbh = DBI->connect("DBI:mysql:host=localhost", "$mysqluser", "$mysqlpass", {'RaiseError' => 1});


        my $rc = $dbh->ping;


        unless ($dbh->ping) { 


            print STDERR "Error, Could not reconnect to MySQLn";


            exit;


        }


    }


    


    undef $abusers;


    undef %counter;


    my $watch = $dbh->prepare("SHOW PROCESSLIST");


    $watch->execute();


    while (my $ref = $watch->fetchrow_hashref()) {


        $counter{$ref->{'User'}} ++;


    }


    foreach $key (keys %counter) {


        if($counter{$key} > $max_concurrent_connections) {


            $abusers .= "$key:$counter{$key}n";


        }


    }    


    if($abusers){


        my $subject = "WatchMySQL: Warning $hostname has MySQL Abusersn";


        my $msg = "The Following Users have exceeded there maximum MySQL concurrent users limitnn Below is a list of users as well as how many times they are connectednn";


        open(SENDMAIL,"|/usr/sbin/sendmail -t");


        print SENDMAIL "To: <$warning_email>n";


        print SENDMAIL "From: WatchMySQL@$hostnamen";


        print SENDMAIL "Subject: $subjectnn";


        print SENDMAIL "$msg$abusers";


        close(SENDMAIL);


    }


    if($kill_user == 1) {


        foreach ($abusers) {


            chomp;


            ($abuser_user,undef) = split(':', $_ , 2);


            my $watch = $dbh->prepare("SHOW PROCESSLIST");


            $watch->execute();


                while (my $ref = $watch->fetchrow_hashref()) {


                if($ref->{'User'} eq $abuser_user) {


                    print "Killed $abuser_usern";


                    $dbh->do("kill $ref->{'Id'}");


                }


            }


        }


    }


    sleep $check_interval;


}




Скачать скрипт: MySQL Watch

Комментариев нет:

Отправить комментарий