diff --git a/check_mysql_slave/Makefile b/check_mysql_slave/Makefile new file mode 100644 index 0000000..cf9673d --- /dev/null +++ b/check_mysql_slave/Makefile @@ -0,0 +1,3 @@ +#/usr/bin/make -f + +include ../common.mk diff --git a/check_mysql_slave/check_mysql_slave b/check_mysql_slave/check_mysql_slave new file mode 100644 index 0000000..7f758e6 --- /dev/null +++ b/check_mysql_slave/check_mysql_slave @@ -0,0 +1,402 @@ +#!/usr/bin/perl +use strict; +my $VERSION = '0.1.1'; +my $COPYRIGHT = 'Copyright (C) 2008 Jonathan Buhacoff '; +my $LICENSE = 'http://www.gnu.org/licenses/gpl.txt'; +my %status = ( 'OK' => 0, 'WARNING' => 1, 'CRITICAL' => 2, 'UNKNOWN' => 3 ); +my $SERVICE = "MYSQL SLAVE"; + +# look for required modules +exit $status{UNKNOWN} unless load_modules(qw/Getopt::Long DBI DBD::mysql/); + +Getopt::Long::Configure("bundling"); +my $verbose = 0; +my $help = ""; +my $help_usage = ""; +my $show_version = ""; +my $mysql_server = ""; +my $default_mysql_port = "3306"; +my $mysql_port = ""; +my $warntime = 15; +my $criticaltime = 30; +my $timeout = 60; +my $username = ""; +my $password = ""; +my $ok; +$ok = Getopt::Long::GetOptions( + "V|version"=>\$show_version, + "v|verbose+"=>\$verbose,"h|help"=>\$help,"usage"=>\$help_usage, + "w|warning=i"=>\$warntime,"c|critical=i"=>\$criticaltime,"t|timeout=i"=>\$timeout, + # mysql settings + "H|hostname=s"=>\$mysql_server,"p|port=i"=>\$mysql_port, + "U|username=s"=>\$username,"P|password=s"=>\$password, + ); + +if( $show_version ) { + print "$VERSION\n"; + if( $verbose ) { + print "Default warning threshold: $warntime seconds\n"; + print "Default critical threshold: $criticaltime seconds\n"; + print "Default timeout: $timeout seconds\n"; + } + exit $status{UNKNOWN}; +} + +if( $help ) { + exec "perldoc", $0 or print "Try `perldoc $0`\n"; + exit $status{UNKNOWN}; +} + +$help_usage = 1 unless $mysql_server and $username; +if( $help_usage ) { + print "Usage: $0 -H host [-p port] [-U username] [-P password] [-w ] [-c ]\n"; + exit $status{UNKNOWN}; +} + +# initialize +my $report = new PluginReport; +my $time_start = time; +my $actual_response = undef; + +# connect to MySQL server +$mysql_port = $default_mysql_port unless $mysql_port; + +eval { + local $SIG{ALRM} = sub { die "exceeded timeout $timeout seconds\n" }; # NB: \n required, see `perldoc -f alarm` + alarm $timeout; + + my $dbh = DBI->connect("DBI:mysql:host=$mysql_server;port=$mysql_port",$username,$password); + # get mysql version + my $version = undef; + my $sth_version = $dbh->prepare("SHOW VARIABLES LIKE 'version'"); + $sth_version->execute; + while( my ($name,$value) = $sth_version->fetchrow_array) { + $version = $value if $name eq "version"; + } + $report->{version} = $version || ""; + $sth_version->finish; + # get slave status (should only be 1 result row) + my $sth_status = $dbh->prepare("SHOW SLAVE STATUS"); + $sth_status->execute; + while( my $status = $sth_status->fetchrow_hashref) { + if( $verbose > 1 ) { + foreach( keys %$status ) { + print "$_ = $status->{$_} \n"; + } + } + # mysql 3.23 has "Slave_Running" while 4.1 and above have "Slave_IO_Running" and "Slave_SQL_Running" + $report->{Running} = "No"; + if( $version lt "4" ) { + $report->{Running} = "Yes" if $status->{Slave_Running}; + $report->{file} = $status->{Log_File}; + $report->{position} = $status->{Pos}; + } + else { + $report->{Running} = "Yes" if $status->{Slave_IO_Running} eq "Yes" and $status->{Slave_SQL_Running} eq "Yes"; + $report->{file} = $status->{Master_Log_File}; + $report->{position} = $status->{Exec_Master_Log_Pos} . '/' . $status->{Read_Master_Log_Pos}; + } + $report->{behind} = $status->{Seconds_Behind_Master}; + # put the master host and its bin log file and position in the report + foreach( keys %$status ) { + $report->{$_} = $status->{$_}; + } + } + $sth_status->finish; + # threshold for seconds behind master etc. + # $report->{behind} = ... + $report->{behind} ||= 0; + # $report->{saomethaisdf} ... + $dbh->disconnect; +}; +if( $@ ) { + $@ = $DBI::errstr if $DBI::errstr; # these can be more helpful than "Can't call method prepare on an undefined value" + $@ =~ s/\n/ /g; # the error message can be multiline but we want our output to be just one line + print "$SERVICE CRITICAL - $@\n"; + exit $status{CRITICAL}; +} + +my @warning = (); +my @critical = (); + +# overall warnings/critical cerrors +push @critical, "not running $report->{Last_Error}" if $report->{Running} ne "Yes"; +push @critical, "$report->{behind} secs behind master" if $report->{behind} > 30; +push @warning, "$report->{behind} secs behind master" if $report->{behind} > 0; +#push @warning, "connection time more than $warntime" if( $time_connected - $time_start > $warntime ); +#push @critical, "connection time more than $criticaltime" if( $time_connected - $time_start > $criticaltime ); +#push @critical, "response was $actual_response but expected $expect_response" if ( $actual_response ne $expect_response ); +# on the number line, we need to test 6 cases: +# 0-----w-----c-----> +# 0, 0=c, w<=lagtext(qw/file position/); +my $long_report = join("", map { "$_: $report->{$_}\n" } qw/version Master_Host Log_File Pos/ ); +if( scalar @critical ) { + my $crit_alerts = join(", ", @critical); + print "$SERVICE CRITICAL - $crit_alerts; $short_report\n"; + print $long_report if $verbose; + exit $status{CRITICAL}; +} +if( scalar @warning ) { + my $warn_alerts = join(", ", @warning); + print "$SERVICE WARNING - $warn_alerts; $short_report\n"; + print $long_report if $verbose; + exit $status{WARNING}; +} +print "$SERVICE OK - $short_report\n"; +print $long_report if $verbose; +exit $status{OK}; + + +# utility to load required modules. exits if unable to load one or more of the modules. +sub load_modules { + my @missing_modules = (); + foreach( @_ ) { + eval "require $_"; + push @missing_modules, $_ if $@; + } + if( @missing_modules ) { + print "Missing perl modules: @missing_modules\n"; + return 0; + } + return 1; +} + + +# NAME +# PluginReport +# SYNOPSIS +# $report = new PluginReport; +# $report->{label1} = "value1"; +# $report->{label2} = "value2"; +# print $report->text(qw/label1 label2/); +package PluginReport; + +sub new { + my ($proto,%p) = @_; + my $class = ref($proto) || $proto; + my $self = bless {}, $class; + $self->{$_} = $p{$_} foreach keys %p; + return $self; +} + +sub text { + my ($self,@labels) = @_; + my @report = map { "$_ $self->{$_}" } grep { defined $self->{$_} } @labels; + my $text = join(", ", @report); + return $text; +} + +package main; +1; + +__END__ + +=pod + +=head1 NAME + +check_mysql_slave - connects to a mysql replication slave and checks its status + +=head1 SYNOPSIS + + check_mysql_slave -H slave.server.net -U nagios -P passwd + check_mysql_slave -H slave.server.net -U nagios -P passwd -p 3306 + check_mysql_slave --help + +=head1 OPTIONS + +=over + +=item --warning + +Currently not used. There are other nagios plugins that will check if a server is responding to connections. +May be used in the future to specify how many bytes or seconds behind the master a slave may be. +Also known as: -w + +=item --critical + +Currently not used. There are other nagios plugins that will check if a server is responding to connections. +May be used in the future to specify how many bytes or seconds behind the master a slave may be. +Also known as: -c + +=item --timeout + +Abort with critical status if it takes longer than to connect to the mysql server. Default is 60 seconds. +Also known as: -t + +=item --hostname + +Address or name of the MySQL slave server. Examples: mysql5.server.net, localhost, 192.168.1.100 +Also known as: -H + +=item --port + +Service port on the MySQL server. Default is 3306. +Also known as: -p + +=item --username + +=item --password + +Username and password to use when connecting to the MySQL server. +Also known as: -U -P + +=item --verbose + +Display additional information. Useful for troubleshooting. Use together with --version to see the default +warning and critical timeout values. +Also known as: -v + +=item --version + +Display plugin version and exit. +Also known as: -V + +=item --help + +Display this documentation and exit. Does not work in the ePN version. +Also known as: -h + +=item --usage + +Display a short usage instruction and exit. + +=back + +=head1 EXAMPLES + +=head2 Command line example + +Check a slave listening on the standard MySQL port from the command line: + +$ check_mysql_slave -H slave.server.net -U nagios -P 'password' + +MYSQL SLAVE OK - file bin.000003, position 41267/41267 + +=head2 Nagios configuration example + +I prefer to define this service on each slave: + + define command { + command_name check_mysql_slave + command_line $USER1$/check_mysql_slave -H $HOSTADDRESS$ -p 3306 -U $ARG1$ -P $ARG2$ + } + + define service { + use your-service-template + host_name slave.server.net + service_description MySQL Replication Slave + check_command check_mysql_slave!nagios!password + } + +But of course you could make the port number an argument and even define all your +slave replication services on the master mysql host and use the slave server's +hostname as an argument instead of HOSTADDRESS, like this: + + command_line $USER1$/check_mysql_slave -H $ARG1$ -p $ARG2$ -U $ARG3$ -P $ARG4$ + + check_command check_mysql_slave!slave.server.net!3306!nagios!password + +=head2 Nagios Embedded-Perl (ePN) example + +The usage is the same, but use the embedded-perl version of the plugin: + + command_line $USER1$/check_mysql_slave_epn -H $ARG1$ -p $ARG2$ -U $ARG3$ -P $ARG4$ + +=head1 EXIT CODES + +This plugin complies with the Nagios plug-in specification: + + 0 OK The plugin was able to check the service and it appeared to be functioning properly + 1 Warning The plugin was able to check the service, but it appeared to be above some "warning" threshold or did not appear to be working properly + 2 Critical The plugin detected that either the service was not running or it was above some "critical" threshold + 3 Unknown Invalid command line arguments were supplied to the plugin or the plugin was unable to check the status of the given hosts/service + +=head1 NAGIOS PLUGIN NOTES + +Nagios plugin reference: http://nagiosplug.sourceforge.net/developer-guidelines.html + +This plugin does NOT use Nagios DEFAULT_SOCKET_TIMEOUT (provided by utils.pm as $TIMEOUT) because +the path to utils.pm must be specified completely in this program and forces users to edit the source +code if their install location is different (if they realize this is the problem). You can view +the default timeout for this module by using the --verbose and --version options together. The +short form is -vV. + +Other than that, it attempts to follow published guidelines for Nagios plugins. + +=head1 SECURITY AND MYSQL PRIVILEGES + +This section concerns mysql administrators who want to grant only minimal privileges to +the nagios plugin (since its username and password are stored in the nagios config!). + +The plugin executes the following commands on slave servers: + + SHOW VARIABLES LIKE 'version'; + SHOW SLAVE STATUS; + +I recommend using the following minimal grants for the nagios plugin: + +=head2 MySQL version 3.23 + + GRANT PROCESS ON *.* TO 'nagios'@'nagios.server.net' identified by 'password'; + +=head2 MySQL version 4.1 + + GRANT SUPER,REPLICATION CLIENT ON *.* TO 'nagios'@'nagios.server.net' identified by 'password'; + +=head2 MySQL version 5.0 + + GRANT SUPER,REPLICATION CLIENT ON *.* TO 'nagios'@'nagios.server.net' identified by 'password'; + +=head1 PERL MODULE NOTES + +This plugin requires the following perl modules: + + Getopt::Long + DBI + DBD::mysql + +The manual for DBD::mysql states that a database is required in the connection string. +This is not true if you are only using global privileges such as usage, process, super, +or replication client without trying to open a specific database. + +=head1 CHANGES + + Tue Aug 19 17:46:02 PDT 2008 + + version 0.1 + Wed Aug 20 07:58:16 PDT 2008 + + added helpful DBI error messages (access denied, incompatible versions, etc) + + version 0.1.1 + +=head1 AUTHOR + +Jonathan Buhacoff + +=head1 COPYRIGHT AND LICENSE + + Copyright (C) 2008 Jonathan Buhacoff + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + http://www.gnu.org/licenses/gpl.txt + +=cut + diff --git a/check_mysql_slave/check_mysql_slave.cfg b/check_mysql_slave/check_mysql_slave.cfg new file mode 100644 index 0000000..7acf914 --- /dev/null +++ b/check_mysql_slave/check_mysql_slave.cfg @@ -0,0 +1,5 @@ +# 'check_mysql_slave' command definition +define command{ + command_name check_slave_mysql + command_line /usr/lib/monitoring-plugins/check_mysql_slave -H '$HOSTADDRESS$' -p '$ARG3$' -U '$ARG1$' -P '$ARG2$' +} diff --git a/check_mysql_slave/control b/check_mysql_slave/control new file mode 100644 index 0000000..c1fab49 --- /dev/null +++ b/check_mysql_slave/control @@ -0,0 +1,6 @@ +Homepage: https://gist.github.com/natedaiger/48457 +Watch: https://gist.github.com/natedaiger/48457/raw/check_mysql_slave.pl \$VERSION\ =\ '([0-9.]+)' +Uploaders: Jan Wagner +Description: plugin that connects to a mysql replication slave and checks its status +Recommends: libdbd-mysql-perl +Version: 0.1.1 diff --git a/check_mysql_slave/copyright b/check_mysql_slave/copyright new file mode 100644 index 0000000..7b47aab --- /dev/null +++ b/check_mysql_slave/copyright @@ -0,0 +1,7 @@ +Copyright (c) 2008 Jonathan Buhacoff + +License: GPL v2 + + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + diff --git a/debian/README.Debian.plugins b/debian/README.Debian.plugins index 891ce28..9f2bff5 100644 --- a/debian/README.Debian.plugins +++ b/debian/README.Debian.plugins @@ -22,6 +22,12 @@ check_bgp: check_file: Required Packages: libtime-modules-perl +check_ipsec: + Required Packages: monitoring-plugins-common | nagios-plugins-common, fping, strongswan-starter | openswan + +check_mysql_slave: + Required Packages: libdbd-mysql-perl + check_nginx_status: Required Packages: libwww-perl, monitoring-plugins-common | nagios-plugins-common diff --git a/debian/control b/debian/control index d6f9c65..92ae062 100644 --- a/debian/control +++ b/debian/control @@ -9,9 +9,9 @@ Vcs-Git: git://github.com/waja/monitoring-plugins-cyconet Vcs-Browser: http://github.com/waja/monitoring-plugins-cyconet Package: monitoring-plugins-cyconet -Architecture: all +Architecture: any Depends: ${misc:Depends} -Recommends: ${shlibs:Depends}, ${python:Depends}, libnet-snmp-perl, monitoring-plugins-common | nagios-plugins-common, libtime-modules-perl, fping, strongswan-starter | openswan, libwww-perl, python-argparse, libredis-perl, ruby-redis, libio-socket-inet6-perl, perl-modules, libnet-tftp-perl, libxml-xpath-perl, ${perl:Depends} +Recommends: ${shlibs:Depends}, ${python:Depends}, libnet-snmp-perl, monitoring-plugins-common | nagios-plugins-common, libtime-modules-perl, fping, strongswan-starter | openswan, libdbd-mysql-perl, libwww-perl, python-argparse, libredis-perl, ruby-redis, libio-socket-inet6-perl, perl-modules, libnet-tftp-perl, libxml-xpath-perl, ${perl:Depends} Suggests: Enhances: nagios-plugins, nagios-plugins-basic, nagios-plugins-standard Description: Plugins for nagios compatible monitoring systems @@ -22,6 +22,7 @@ Description: Plugins for nagios compatible monitoring systems * check_bgp (0.4): plugin to check BGP peer status via SNMP. * check_file: plugin to check file count, size and ages * check_ipsec (2.0): plugin checking ipsec connections from open- or stongswan + * check_mysql_slave (0.1.1): plugin that connects to a mysql replication slave and checks its status * check_nginx_status (0.10): plugin checking the nginx_status page report from nginx Tracking Active connections processes, request per second, connections per seconds, Connections status. diff --git a/debian/copyright b/debian/copyright index c573054..709e468 100644 --- a/debian/copyright +++ b/debian/copyright @@ -74,6 +74,22 @@ https://raw.githubusercontent.com/Inuits/monitoring-plugins/master/check_ipsec +------------------------------------------------------------------------------ + +check_mysql_slave: + +The plugin was downloaded from: +https://gist.github.com/natedaiger/48457 + + Copyright (c) 2008 Jonathan Buhacoff + + License: GPL v2 + + On Debian systems, the complete text of the GNU General + Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". + + + ------------------------------------------------------------------------------ check_nginx_status: diff --git a/debian/patches/check_mysql_slave/epn b/debian/patches/check_mysql_slave/epn new file mode 100644 index 0000000..8855958 --- /dev/null +++ b/debian/patches/check_mysql_slave/epn @@ -0,0 +1,10 @@ +diff --git a/check_mysql_slave/check_mysql_slave b/check_mysql_slave/check_mysql_slave +index 7f758e6..435c341 100644 +--- a/check_mysql_slave/check_mysql_slave ++++ b/check_mysql_slave/check_mysql_slave +@@ -1,4 +1,5 @@ + #!/usr/bin/perl ++# nagios: -epn + use strict; + my $VERSION = '0.1.1'; + my $COPYRIGHT = 'Copyright (C) 2008 Jonathan Buhacoff '; diff --git a/debian/patches/series b/debian/patches/series index 2c1d644..d86b62d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -1,8 +1,9 @@ -check_tomcat/epn -check_tftp/epn -check_phpfpm_status/10_pathes -check_sieve/epn -check_sieve/10_pathes check_ipsec/10_pathes check_ipsec/15_fix_syntax check_ipsec/20_remove_gateway +check_mysql_slave//epn +check_phpfpm_status/10_pathes +check_sieve/epn +check_sieve/10_pathes +check_tftp/epn +check_tomcat/epn