#!/usr/bin/perl #use strict; use DBI; use DBD::mysql; use POSIX; ($sysname, $hostname, $release, $version, $machine) = POSIX::uname(); my $slowtime=1; # my $warnlevel=5; # my $warncounter=5; # $warncounter my $alarmcounter=10; # >= $alarmcounter my $socket='/tmp/mysql56.sock'; # my $email="admin\@myemail.net"; # my $wrkdir='/tmp/'; my $procfile=$wrkdir.'alarm.proclist'; # my $datfile=$wrkdir.'alarm.dat'; # my $pidfile=$wrkdir.'alarm.pid'; # pid . mysql if (-e "$pidfile") { printf("pid file found. Exit.\n"); exit(255); } open (PIDFILE,">$pidfile") || die "cant create $pidfile\n"; print PIDFILE "$$\n"; close PIDFILE; open (PROCFILE,">$procfile") || die "cant create $procfile\n"; my ($proc, $dbh, $sth, $totalcounter, $slowcounter, $sleepcounter, $user, $time, $state, $command, $info, $i); until ($dbh = DBI->connect("DBI:mysql:mysql_socket=$socket", "user", "password")){ unlink($pidfile); die("Can't connect: $DBI::errstr\n"); } $sth = $dbh->prepare("SHOW FULL PROCESSLIST"); $sth->execute; my @proclist=(); $totalcounter=$slowcounter=$sleepcounter=0; while (my $row = $sth->fetchrow_hashref()) { $user=$row->{'User'}; $time=$row->{'Time'}; $state=$row->{'State'}; $command=$row->{'Command'}; $info=$row->{'Info'}; $totalcounter++; next if ($user =~ m/root/); if ($command =~ m/(Sleep|Delayed|Binlog)/){ $sleepcounter++; next; }; ### statistics if ($state =~ m/statistics/ && $time > 5){ $statinfo="$user: killed $mid: $dbuser | $db | $time | $state | $command | $info\n\n"; $sth2 = $dbh->prepare("kill $mid"); $sth2->execute; $sth2->finish; open (MAIL,"|/usr/sbin/sendmail -F$hostname $email"); print MAIL "To:$email\nSubject:".$subj."Hanged query in the statistics state: $hostname, user $user \n\n"; print MAIL $statinfo; close (MAIL); }; ### if ($time>$slowtime) { $slowcounter++; } $info =~ s/[\r\n\t]+/ /g; push (@proclist,sprintf("%-24s | %4d | %s | %s | %s \n", $user, $time, $state, $command, $info)); printf PROCFILE ("%-24s | %4d | %s | %s | %s \n", $user, $time, $state, $command, $info); } $sth->finish; close PROCFILE; #print "--- $slowcounter slow queries from total $totalcounter ($sleepcounter are sleep) ---- \n"; my @data=(); ### read slowcounter timings from dat file open (DATFILE,"<$datfile"); while(<DATFILE>){ my($line) = $_; chomp($line); push (@data,$line); } close(DATFILE); ### if dat file is smaller than warnlevel then fill timings by zeros if (scalar(@data)<$warnlevel) { for $i ( 0 .. $warnlevel-scalar(@data) ) { push (@data,0); } } ### shift timings with last slowcounter push (@data,$slowcounter); shift(@data); ### dumping slowcounter timings to dat file open (DATFILE,"+>$datfile") || die "cant create $datfile\n"; foreach (@data) { print DATFILE "$_\n"; } close(DATFILE); ### get number of bad states for last minutes my $cnt=0; foreach (@data) { if($_ >= $warnlevel) { $cnt++; } } my $subj=" "; if ($slowcounter>=$alarmcounter) { # very critical state $subj=" VERY "; } my $warnmessage="Critical state of $hostname! There was a $warncounter checks with at least $warnlevel long queries!\n"; if ($slowcounter>=$alarmcounter) { # very critical state $warnmessage=$warnmessage."--- !!! Last check shows $slowcounter long queries!\n"; } if (($cnt >= $warncounter) || $slowcounter>=$alarmcounter){ open (MAIL,"|/usr/sbin/sendmail -F$hostname $email"); print MAIL "To:$email\nSubject:".$subj."Critical state of $hostname\n\n"; print MAIL $warnmessage; print MAIL "---------------------------------------------------------------------------------------------------\n"; print MAIL "--- $slowcounter slow queries from total $totalcounter ($sleepcounter are sleep) \n"; print MAIL "---------------------------------------------------------------------------------------------------\n"; foreach (@proclist) { print MAIL "$_"; } close (MAIL); } unlink($pidfile);
Source: https://habr.com/ru/post/145573/
All Articles