#!/usr/bin/perl use DBI; use Time::Local; use FileHandle; use strict; our $dbh; my ($p_file,$p_offset,$p_warn,$p_crit,$p_sqlhost,$p_sqlport,$p_sqluser,$p_sqlpass,$p_dbname); $p_sqlhost = '127.0.0.1'; $p_sqlport = '3306'; $p_sqluser = 'root'; $p_sqlpass = ''; $p_dbname = 'dnsdatadb'; $p_offset = 1800; $p_warn = 10; $p_crit = 300; $p_file = "/var/tmp/replcheck"; if ( $ARGV[0] eq "-help" || $ARGV[0] eq "--help" ){ help(); exit(1); } my %par; if ( $ARGV[0] ne "" ){ my $chk = @ARGV; for ( my $i = 0; $i < $chk; $i = $i + 2 ){ if ($ARGV[$i] =~ /^\-/ ){ my $key = $ARGV[$i]; $key =~ s/^\-//ig; my $j = $i + 1; $par{$key} = $ARGV[$j]; } } } #while( my ($key,$value) = each %par){ # print "$key => $value\n"; #} $p_sqlhost = $par{'sqlhost'} if ($par{'sqlhost'} ne "" ); $p_sqlport = $par{'sqlport'} if ($par{'sqlport'} ne "" ); $p_sqluser = $par{'sqluser'} if ($par{'sqluser'} ne "" ); $p_sqlpass = $par{'sqlpass'} if ($par{'sqlpass'} ne "" ); $p_dbname = $par{'sqldb'} if ($par{'sqldb'} ne "" ); $p_offset = $par{'offset'} if ($par{'offset'} ne "" ); $p_warn = $par{'warn'} if ($par{'warn'} ne "" ); $p_crit = $par{'crit'} if ($par{'crit'} ne "" ); $p_file = $par{'file'} if ($par{'file'} ne "" ); connect_db($p_sqlhost,$p_sqlport,$p_sqluser,$p_sqlpass,$p_dbname); if ( $p_crit < $p_warn ){ print "Critical alert offset cannot be less than warning alert offset\n"; exit(1); } my $pointer = $p_file; my $logpos = get_mysql_status(0); my $sec_to_master = get_mysql_status(1); if ( $sec_to_master > $p_warn ){ print "Warning! The parameter \"seconds behind master\" greater than $p_warn ($sec_to_master)\n"; exit(1); } elsif ( $sec_to_master > $p_crit ){ print "CRITICAL! The parameter \"seconds behind master\" greater than $p_crit sec ($sec_to_master)\n"; exit(2); } my $chk_step = $p_offset; my $time = time(); my $timeleft; if ( -e $pointer ){ open (LOG,"$pointer") || error("Cannot open file"); my @strs = ; close(LOG); my ($logtime,$chkpos) = split( /-/, $strs[0]); chomp($chkpos); my $chktime = $time - $chk_step; my $timefut = $logtime + $chk_step; $timeleft = $timefut - $time; if ( $logtime < $chktime ){ if ( $chkpos != $logpos ){ #print "Different - $chkpos - $logpos\n"; } else { #print "The same! $chkpos - $logpos\n"; error("No changes during $chk_step seconds"); } put_result($pointer, $logpos, $time); print "OK\n"; exit(0); } } else { #print "There is no logfile. Creating...\n"; put_result($pointer, $logpos, $time); } print "Waiting for next check... $timeleft seconds left\n"; exit(0); sub error { my $reason = shift; print "CRITICAL - $reason\n"; exit(2); } sub put_result { my $pointer = shift; my $logpos = shift; my $time = shift; open (FILE, ">$pointer") || error("Cannot open logfile"); print FILE "$time-$logpos\n"; close(FILE); } sub get_mysql_status { my $request = shift; my $res; my $sth = $dbh->prepare("show slave status"); $sth->execute; my $result = $sth->fetchrow_hashref(); # print "$result->{'Exec_Master_Log_Pos'}\n"; if ( $request == 1 ){ $res = $result->{'Seconds_Behind_Master'}; } else { $res = $result->{'Exec_Master_Log_Pos'}; } return($res); } sub connect_db{ my ($db_base, $db_host, $db_user, $db_pass, $db_enc); my $db_host = shift; my $db_port = shift; my $db_user = shift; my $db_pass = shift; my $db_name = shift; $db_enc = 'utf8'; my $dsn = "DBI:mysql:$db_name:$db_host:$db_port"; $dbh = DBI->connect($dsn, $db_user, $db_pass) || error("MySQL error"); my $sth = $dbh->do("set names \'$db_enc\'"); } sub help { my $script = $0; print <<"[END]"; The script $script made as NRPE plugin. It\'s checking MySQL slave status and generates the correspondent status message. The command line should be the next: $script [option1] [value1] [option2] [value2] ... [optionN] [valueN] You can specify the next options in command line running the script: -offset [seconds] - Option that specifies the frequency of comparing of "Exec_Master_Log_Pos" values. If the values stays the same after this time, you get CRITICAL status. Default value: 1800 (30 min) -warn [seconds] - Option that specifies the value of "Seconds_Behind_Master" when the script start returning of WARNING status. Default value: 10 -crit [seconds] - Option that specifies the value of "Seconds_Behind_Master" when the script start returning CRITICAL status. Default value: 300 -sqlhost [address] - MySQL server address Default value: localhost -sqlport [port] - MySQL server port Default value: 3306 -sqluser [username]- MySQL username Deafult: root -sqlpass [password]- MySQL password Default: -sqldb [name] - Database name Default: dnsdatadb -file [/path/file] - File to store time and "Exec_Master_Log_Pos" values. Default: /var/tmp/replcheck -help Show this help Sample: $script -offset 1800 -warn 10 -crit 300 -sqlhost localhost -sqlport 3306 -sqluser root -sqlpass password -sqldb dnsdatadb -file /var/tmp/replcheck $script -offset 1800 -warn 10 -crit 300 -sqlhost localhost $script -sqlhost localhost -sqlport 3306 -sqluser root -sqlpass password [END] exit; }