mirror of
https://github.com/pandorafms/pandorafms.git
synced 2025-07-31 01:35:36 +02:00
When /usr/lib/perl5 is added to the front of the module search path it takes precedence over libraries distributed with binary versions of Pandora FMS. This can be fixed by pushing it to the back instead.
1189 lines
35 KiB
Perl
1189 lines
35 KiB
Perl
#!/usr/bin/perl
|
|
# Pandora FMS Plugin for MySQL
|
|
# (c) Artica ST 2015
|
|
# v1.4, 19 Feb 2015
|
|
# ----------------------------------------------------------------------
|
|
|
|
# Default lib dir for RPM and DEB packages
|
|
BEGIN { push @INC, '/usr/lib/perl5'; }
|
|
|
|
use strict;
|
|
use Data::Dumper;
|
|
use POSIX qw(setsid strftime);
|
|
use POSIX;
|
|
use Time::Local;
|
|
|
|
#---------------------------- Global parameters -----------------------#
|
|
|
|
# OS and OS version
|
|
my $OS = $^O;
|
|
|
|
# Store original PATH
|
|
my $ORIGINAL_PATH = $ENV{'PATH'};
|
|
|
|
# FLUSH in each IO
|
|
$| = 1;
|
|
|
|
# Conf file divided line by line
|
|
my @config_file;
|
|
# Conf filename received by command line
|
|
my $archivo_cfg = $ARGV[0];
|
|
# Hash with this plugin setup
|
|
my %plugin_setup;
|
|
# Array with different block checks
|
|
my @checks;
|
|
|
|
# ----------------------------------------------------------------------
|
|
# parse_dosline (line)
|
|
#
|
|
# This cleans DOS-like line and cleans ^M character. VERY Important when
|
|
# you process .conf edited from DOS
|
|
# ----------------------------------------------------------------------
|
|
sub parse_dosline ($){
|
|
my $str = $_[0];
|
|
|
|
$str =~ s/\r//g;
|
|
return $str;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# load_external_setup (config file)
|
|
#
|
|
# Loads a config file
|
|
# ----------------------------------------------------------------------
|
|
sub load_external_setup ($){
|
|
my $archivo_cfg = $_[0];
|
|
my $buffer_line;
|
|
|
|
# Collect items from config file and put in an array
|
|
if (! open (CFG, "< $archivo_cfg")) {
|
|
print "[ERROR] Error opening configuration file $archivo_cfg: $!.\n";
|
|
logger ("[ERROR] Error opening configuration file $archivo_cfg: $!");
|
|
exit 0;
|
|
}
|
|
|
|
while (<CFG>) {
|
|
$buffer_line = parse_dosline ($_);
|
|
# Parse configuration file, this is specially difficult because can contain SQL code, with many things
|
|
if ($buffer_line !~ /^\#/) { # begins with anything except # (for commenting)
|
|
if ($buffer_line =~ m/(.+)\s(.*)/) {
|
|
push @config_file, $buffer_line;
|
|
}
|
|
}
|
|
}
|
|
|
|
close (CFG);
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# logger_begin (message)
|
|
# Beggining of logging to file
|
|
# ----------------------------------------------------------------------
|
|
sub logger_begin ($) {
|
|
my ($message) = @_;
|
|
|
|
my $file = "/tmp/pandora_mysql";
|
|
|
|
if (! open (FILE, "> $file")) {
|
|
print "[ERROR] Could not open logfile '$file' \n";
|
|
logger ("[ERROR] Error opening logfile $file");
|
|
exit 0;
|
|
}
|
|
|
|
# open (FILE, "> $file") or die "[FATAL] Could not open logfile '$file'";
|
|
print FILE strftime ("%Y-%m-%d %H:%M:%S", localtime()) . " >> " . $message . "\n";
|
|
close (FILE);
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# logger (message)
|
|
# Log to file
|
|
# ----------------------------------------------------------------------
|
|
sub logger ($) {
|
|
my ($message) = @_;
|
|
|
|
my $file = "/tmp/pandora_mysql";
|
|
|
|
if (! open (FILE, ">> $file")) {
|
|
print "[ERROR] Could not open logfile '$file' \n";
|
|
logger ("[ERROR] Error opening logfile $file");
|
|
exit 0;
|
|
}
|
|
|
|
print FILE strftime ("%Y-%m-%d %H:%M:%S", localtime()) . " >> " . $message . "\n";
|
|
close (FILE);
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# trim (string)
|
|
#
|
|
# Erase blank spaces before and after the string
|
|
# ----------------------------------------------------------------------
|
|
sub trim ($) {
|
|
my $string = shift;
|
|
$string =~ s/^\s+//;
|
|
$string =~ s/\s+$//;
|
|
|
|
return $string;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# clean_blank (string)
|
|
#
|
|
# This function return a string without blankspaces, given a simple text
|
|
# string
|
|
# ----------------------------------------------------------------------
|
|
sub clean_blank($) {
|
|
my $input = $_[0];
|
|
$input =~ s/[\s\r\n]*//g;
|
|
|
|
return $input;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# print_module (module name, module type, module value, module
|
|
# description, [module severity])
|
|
#
|
|
# This function returns a XML module part for the plugin
|
|
# ----------------------------------------------------------------------
|
|
sub print_module ($$$$;$) {
|
|
my $MODULE_NAME = $_[0];
|
|
my $MODULE_TYPE = $_[1];
|
|
my $MODULE_VALUE = $_[2];
|
|
my $MODULE_DESC = $_[3];
|
|
my $MODULE_SEVERITY = $_[4];
|
|
|
|
# If not a string type, remove all blank spaces and check for not value returned!
|
|
if ($MODULE_TYPE !~ m/string/) {
|
|
$MODULE_VALUE = clean_blank($MODULE_VALUE);
|
|
}
|
|
|
|
print "<module>\n";
|
|
print "<name>$MODULE_NAME</name>\n";
|
|
print "<type>$MODULE_TYPE</type>\n";
|
|
print "<data><![CDATA[$MODULE_VALUE]]></data>\n";
|
|
print "<description><![CDATA[$MODULE_DESC]]></description>\n";
|
|
if (defined($MODULE_SEVERITY)) {
|
|
print "<status>$MODULE_SEVERITY</status>\n";
|
|
} else {
|
|
print "<status>NORMAL</status>\n";
|
|
}
|
|
|
|
print "</module>\n";
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# parse_config
|
|
#
|
|
# This function load configuration tokens and store in a global hash
|
|
# called %plugin_setup accesible on all program.
|
|
# ----------------------------------------------------------------------
|
|
sub parse_config {
|
|
|
|
my $check_block = 0;
|
|
my $parametro;
|
|
|
|
# Some default options
|
|
$plugin_setup{"conf_mysql_homedir"} = "/var/lib/mysql";
|
|
$plugin_setup{"conf_mysql_basedir"} = "/var/lib/mysql";
|
|
$plugin_setup{"conf_temp"} = "/tmp";
|
|
$plugin_setup{"numchecks"} = 0;
|
|
$plugin_setup{"conf_mysql_version"} = "5.5";
|
|
|
|
foreach (@config_file) {
|
|
$parametro = $_;
|
|
|
|
if ($parametro =~ m/^include\s(.*)/i) {
|
|
load_external_setup ($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_version\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_version"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_user\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_user"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_pass\s(.*)/i) {
|
|
my $temp = $1;
|
|
$temp =~ s/\"//g;
|
|
$plugin_setup{"conf_mysql_pass"} = trim($temp);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_host\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_host"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_homedir\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_homedir"} = trim($1);
|
|
}
|
|
if ($parametro =~ m/^conf\_mysql\_basedir\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_basedir"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_mysql\_logfile\s(.*)/i) {
|
|
$plugin_setup{"conf_mysql_logfile"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_temp\s(.*)/i) {
|
|
$plugin_setup{"conf_temp"} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^conf\_logparser\s(.*)/i) {
|
|
$plugin_setup{"conf_logparser"} = trim($1);
|
|
}
|
|
|
|
# Detect begin of check definition
|
|
if ($parametro =~ m/^check\_begin/i) {
|
|
$check_block = 1;
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'unknown';
|
|
}
|
|
|
|
############### Specific check block parsing ###################
|
|
if ($check_block == 1) {
|
|
|
|
if ($parametro =~ m/^check\_end/i) {
|
|
$check_block = 0;
|
|
$plugin_setup{"numchecks"}++;
|
|
}
|
|
|
|
# Try to parse check type (System parameters)
|
|
if ($parametro =~ m/^check\_mysql\_service/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_service';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_mysql\_memory/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_memory';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_mysql\_cpu/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_cpu';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_system\_timewait/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'system_timewait';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_system\_diskusage/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'system_diskusage';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_mysql\_ibdata1/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_ibdata1';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_mysql\_logs/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_logs';
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_mysql\_connect/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'mysql_connection';
|
|
}
|
|
|
|
|
|
# Try to parse check type (Performance parameters)
|
|
if ($parametro =~ m/^mysql\_status\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'status';
|
|
$checks[$plugin_setup{"numchecks"}]{'show'} = trim($1);
|
|
}
|
|
|
|
# Try to parse check type (Open SQL interface)
|
|
if ($parametro =~ m/^check\_sql\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'sql';
|
|
$checks[$plugin_setup{"numchecks"}]{'sql'} = trim($1);
|
|
}
|
|
|
|
# Try to parse check type (Query Innodb status)
|
|
if ($parametro =~ m/^mysql\_innodb\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'type'} = 'innodb';
|
|
$checks[$plugin_setup{"numchecks"}]{'query'} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_name\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'check_name'} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^check\_schema\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'check_schema'} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^module\_type\s(generic_data|generic_data_inc|generic_data_string|generic_proc|async_string|async_proc|async_data)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'module_type'} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^post\_condition\s+(==|!=|<|>)\s+(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'postcondition_op'} = trim($1);
|
|
$checks[$plugin_setup{"numchecks"}]{'postcondition_val'} = trim($2);
|
|
}
|
|
|
|
if ($parametro =~ m/^post\_execution\s(.*)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'postexecution'} = trim($1);
|
|
}
|
|
|
|
if ($parametro =~ m/^data\_absolute/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'return_type'} = 'data_absolute';
|
|
}
|
|
|
|
if ($parametro =~ m/^data\_delta/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'return_type'} = 'data_delta';
|
|
}
|
|
|
|
if ($parametro =~ m/^post\_status\s(WARNING|CRITICAL)/i) {
|
|
$checks[$plugin_setup{"numchecks"}]{'status'} = trim($1);
|
|
}
|
|
|
|
} # Check block
|
|
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_service
|
|
#
|
|
# This function check MySQL service status
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_service {
|
|
my ($mysql_service_result1, $mysql_service_result2, $mysql_service_result3, $mysql_service_result4);
|
|
my $mysql_service_result = 0;
|
|
|
|
# Try different flavours of mysql status
|
|
$mysql_service_result1 = `service mysql status 2> /dev/null`;
|
|
$mysql_service_result2 = `service mysqld status 2> /dev/null`;
|
|
$mysql_service_result3 = `/etc/init.d/mysql status 2> /dev/null`;
|
|
$mysql_service_result4 = `/etc/init.d/mysqld status 2> /dev/null`;
|
|
|
|
|
|
#print "1 >> " . $mysql_service_result1 . "\n";
|
|
#print "2 >> " . $mysql_service_result2 . "\n";
|
|
#print "3 >> " . $mysql_service_result3 . "\n";
|
|
#print "4 >> " . $mysql_service_result4 . "\n";
|
|
|
|
# If any of these ones is up then check result eq OK!
|
|
if (($mysql_service_result1 =~ /start/i) || ($mysql_service_result1 =~ /running/i) ||
|
|
($mysql_service_result2 =~ /start/i) || ($mysql_service_result2 =~ /running/i) ||
|
|
($mysql_service_result3 =~ /start/i) || ($mysql_service_result3 =~ /running/i) ||
|
|
($mysql_service_result4 =~ /start/i) || ($mysql_service_result4 =~ /running/i)) {
|
|
|
|
# OK!
|
|
$mysql_service_result = 1;
|
|
|
|
} else {
|
|
|
|
# Fail
|
|
$mysql_service_result = 0;
|
|
|
|
}
|
|
|
|
logger("[INFO] check_mysql_service with result: " . $mysql_service_result);
|
|
|
|
return $mysql_service_result;
|
|
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_memory
|
|
#
|
|
# This function check MySQL memory usage
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_memory {
|
|
my $mysql_memory_result = 0;
|
|
|
|
# Depends on OS
|
|
if ($OS =~ /hpux/i){
|
|
$mysql_memory_result = `ps -eo comm,pmem | grep -v "grep" | grep "mysqld --basedir" | awk '{print \$2}'`;
|
|
} else {
|
|
$mysql_memory_result = `ps aux | grep -v "grep" | grep "mysqld --basedir" | awk '{print \$4}'`;
|
|
}
|
|
|
|
logger("[INFO] check_mysql_memory with result: " . $mysql_memory_result);
|
|
|
|
return $mysql_memory_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_cpu
|
|
#
|
|
# This function check MySQL cpu usage
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_cpu {
|
|
my $mysql_cpu_result = 0;
|
|
|
|
# Depends on OS
|
|
if ($OS =~ /hpux/i){
|
|
$mysql_cpu_result = `ps -eo comm,pcpu | grep -v "grep" | grep "mysqld --basedir" | awk '{print \$2}'`;
|
|
} else {
|
|
$mysql_cpu_result = `ps aux | grep -v "grep" | grep "mysqld --basedir" | awk '{print \$3}'`;
|
|
}
|
|
|
|
logger("[INFO] check_mysql_cpu with result: " . $mysql_cpu_result);
|
|
|
|
return $mysql_cpu_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_system_timewait
|
|
#
|
|
# This function check system timewait
|
|
# ----------------------------------------------------------------------
|
|
sub check_system_timewait {
|
|
my $system_timewait_result = 0;
|
|
|
|
$system_timewait_result = `netstat -ntu | grep "TIME_WAIT" | wc -l`;
|
|
|
|
logger("[INFO] check_system_timewait with result: " . $system_timewait_result);
|
|
|
|
return $system_timewait_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_system_diskusage
|
|
#
|
|
# This function check system disk usage
|
|
# ----------------------------------------------------------------------
|
|
sub check_system_diskusage {
|
|
my $system_diskusage_result_tmp = 0;
|
|
my $system_diskusage_result = 0;
|
|
|
|
if (!defined($plugin_setup{"conf_mysql_homedir"})) {
|
|
logger("[INFO] system_diskusage_result check needs conf_mysql_homedir token defined in configuration file.");
|
|
return 0;
|
|
}
|
|
|
|
my $system_diskusage_result_tmp = `df -k "$plugin_setup{'conf_mysql_homedir'}" | awk '{print \$5}' | tail -1 | tr -d "%"`;
|
|
|
|
$system_diskusage_result = 100 - $system_diskusage_result_tmp;
|
|
|
|
logger("[INFO] check_system_diskusage with result: " . $system_diskusage_result);
|
|
|
|
return $system_diskusage_result;
|
|
}
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_ibdata1
|
|
#
|
|
# This function check ibdata1 file disk usage
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_ibdata1 {
|
|
my $mysql_ibdata1_result = 0;
|
|
|
|
if (!defined($plugin_setup{"conf_mysql_basedir"})) {
|
|
logger("[INFO] check_mysql_ibdata1 check needs conf_mysql_basedir token defined in configuration file.");
|
|
}
|
|
|
|
$mysql_ibdata1_result = `du -k $plugin_setup{"conf_mysql_basedir"}/ibdata1 | tail -1 | awk '{ print \$1 }'`;
|
|
|
|
logger("[INFO] check_mysql_ibdata1 with result: " . $mysql_ibdata1_result);
|
|
|
|
return $mysql_ibdata1_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_connection
|
|
#
|
|
# This function check connection against MySQL, if goes wrong abort monitoring
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_connection {
|
|
my $mysql_connection_result = 1;
|
|
my $connection_string = 0;
|
|
if (!defined($plugin_setup{"conf_mysql_pass"})){
|
|
$connection_string = "mysql -u" . $plugin_setup{"conf_mysql_user"} .
|
|
" -h" . $plugin_setup{"conf_mysql_host"} ;
|
|
}else{
|
|
# Connection string
|
|
$connection_string = "mysql -u" . $plugin_setup{"conf_mysql_user"} .
|
|
" -p" . $plugin_setup{"conf_mysql_pass"} .
|
|
" -h" . $plugin_setup{"conf_mysql_host"} ;
|
|
}
|
|
my $tmp_file = $plugin_setup{'conf_temp'} . '/mysql_connection.tmp';
|
|
|
|
my $connection_result = `$connection_string -e "SELECT 1 FROM DUAL" 2> $tmp_file`;
|
|
|
|
# Collect info from temp file
|
|
open (TMP, "< $tmp_file");
|
|
|
|
while (<TMP>) {
|
|
my $buffer_line = parse_dosline ($_);
|
|
|
|
if ($buffer_line =~ /error/i) {
|
|
$mysql_connection_result = 0;
|
|
}
|
|
}
|
|
|
|
close (TMP);
|
|
|
|
unlink($tmp_file);
|
|
|
|
logger("[INFO] check_mysql_connection with result: " . $mysql_connection_result);
|
|
|
|
# Abort monitoring
|
|
if ($mysql_connection_result == 0) {
|
|
print_module("MySQL_connection_error", "async_string", "Error", "MySQL plugin cannot connect to Database. Abort execution of plugin", "CRITICAL");
|
|
}
|
|
|
|
return $mysql_connection_result;
|
|
}
|
|
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_logs
|
|
#
|
|
# This function check ibdata1 file disk usage
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_logs(;$) {
|
|
my $module_type = $_[0];
|
|
|
|
my $mysql_logs_result = 0;
|
|
|
|
if (!defined($plugin_setup{"conf_logparser"})) {
|
|
logger("[INFO] check_mysql_logs check needs conf_logparser token defined in configuration file.");
|
|
return 0;
|
|
}
|
|
|
|
if (!defined($plugin_setup{"conf_logparser"})) {
|
|
logger("[INFO] check_mysql_logs check needs conf_mysql_logfile token defined in configuration file.");
|
|
return 0;
|
|
}
|
|
|
|
my $plugin_call = $plugin_setup{"conf_logparser"}. " " . $plugin_setup{"conf_mysql_logfile"} . " MySQL_error_logs error 2> /dev/null";
|
|
|
|
$mysql_logs_result = `$plugin_call`;
|
|
|
|
if ($mysql_logs_result ne "") {
|
|
logger ("[INFO] check_mysql_logs with result:\n$mysql_logs_result");
|
|
print $mysql_logs_result;
|
|
|
|
# Process output of grep_log plugin
|
|
my @temp = split ("\n", $mysql_logs_result);
|
|
my @result;
|
|
|
|
# Try to get return values
|
|
my $i = 0;
|
|
foreach (@temp) {
|
|
# Get return values
|
|
if ($_ =~ /<data><value><!\[CDATA\[(.*)\]\]><\/value><\/data>/){
|
|
$result[$i] = $1;
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
return @result;
|
|
|
|
} else {
|
|
logger ("[INFO] Blank output in check_mysql_logs searching in logfile: " . $plugin_setup{"conf_mysql_logfile"});
|
|
|
|
# if (defined($module_type)) {
|
|
# print_module("MySQL_error_logs", $module_type, "Blank output", "Blank output in check_mysql_logs searching in logfile " . $plugin_setup{"conf_mysql_logfile"});
|
|
# } else {
|
|
# print_module("MySQL_error_logs", "async_string", "Blank output", "Blank output in check_mysql_logs searching in logfile " . $plugin_setup{"conf_mysql_logfile"});
|
|
# }
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# check_mysql_status (SHOW parameter, [SQL statement/ Query for Innodb status, Mysql_schema])
|
|
#
|
|
# This function check status parameter (Performance parameters)
|
|
# ----------------------------------------------------------------------
|
|
sub check_mysql_status($;$$) {
|
|
my $show_parameter = $_[0];
|
|
my $sql_statement = $_[1];
|
|
my $sql_schema = $_[2];
|
|
my $mysql_status_result = 0;
|
|
|
|
if (!defined($show_parameter)){
|
|
logger("[INFO] Empty parameter in check_mysql_status check, please revise configuration file.");
|
|
return 0;
|
|
}
|
|
|
|
# Writes in temp file
|
|
my $temp_file = $plugin_setup{"conf_temp"} . "/mysql_pandora.tmp";
|
|
|
|
open (TEMP1, "> " . $temp_file);
|
|
|
|
# Depends on the request write different statements ('pending_io', 'sql', 'innodb' is different)
|
|
if ($show_parameter =~ /processlist/i) {
|
|
print TEMP1 "SHOW " . $show_parameter;
|
|
} elsif ($show_parameter =~ /total_size/i) {
|
|
print TEMP1 "SELECT \"Total_size\",
|
|
sum( data_length + index_length ) / 1024 / 1024 / 1024 \"Data Base Size in GB\"
|
|
FROM information_schema.TABLES";
|
|
} elsif (($show_parameter !~ /pending_io/i) and ($show_parameter !~ /sql/i) and ($show_parameter ne 'innodb')) {
|
|
print TEMP1 "SHOW GLOBAL STATUS LIKE '" . $show_parameter . "'";
|
|
}
|
|
|
|
close (TEMP1);
|
|
|
|
# Connection string
|
|
my $connection_string = 0;
|
|
if (!defined($plugin_setup{"conf_mysql_pass"} ) ){
|
|
$connection_string = "mysql -u" . $plugin_setup{"conf_mysql_user"} .
|
|
" -h" . $plugin_setup{"conf_mysql_host"} ;
|
|
}else{
|
|
$connection_string = "mysql -u" . $plugin_setup{"conf_mysql_user"} .
|
|
" -p" . $plugin_setup{"conf_mysql_pass"} .
|
|
" -h" . $plugin_setup{"conf_mysql_host"} ;
|
|
}
|
|
#my $connection_string = "mysql -u" . $plugin_setup{"conf_mysql_user"} .
|
|
# " -p" . $plugin_setup{"conf_mysql_pass"} .
|
|
# " -h" . $plugin_setup{"conf_mysql_host"} ;
|
|
|
|
# If its a query, then try to add schema to the connection string
|
|
if ($show_parameter =~ /sql/i) {
|
|
if (defined($sql_schema)) {
|
|
$connection_string .= " $sql_schema";
|
|
}
|
|
}
|
|
|
|
my $post_sql = '';
|
|
# If we want to retrieve 'active sessions' count lines
|
|
if ($show_parameter =~ /processlist/i) {
|
|
$post_sql = ' | wc -l';
|
|
} # Rest of request have this suffix
|
|
else {
|
|
$post_sql = ' | tail -1 | awk \'{print $2}\'';
|
|
}
|
|
|
|
# 'pending_io' and 'sql' and 'innodb' are different
|
|
if (($show_parameter !~ /pending_io/i) and ($show_parameter !~ /sql/i) and ($show_parameter ne 'innodb')) {
|
|
$mysql_status_result = `$connection_string < $temp_file $post_sql`;
|
|
} elsif ($show_parameter =~ /sql/i) {
|
|
$mysql_status_result = `$connection_string -e "$sql_statement" | tail -1`;
|
|
} elsif ($show_parameter =~ /innodb/i) {
|
|
|
|
|
|
if ($plugin_setup{"conf_mysql_version"} == "5.0") {
|
|
$mysql_status_result = `$connection_string -e "SHOW INNODB STATUS\\G"`;
|
|
} else {
|
|
$mysql_status_result = `$connection_string -e "SHOW ENGINE INNODB STATUS\\G"`;
|
|
}
|
|
|
|
# Process output of show innodb status
|
|
my @temp = split ("\n", $mysql_status_result);
|
|
|
|
# If we detect query lines then output
|
|
$mysql_status_result = 0;
|
|
foreach (@temp) {
|
|
if ($_ =~ m/$sql_statement\s+(.*)/) {
|
|
$mysql_status_result = $1;
|
|
}
|
|
}
|
|
|
|
} else {
|
|
|
|
if ($plugin_setup{"conf_mysql_version"} == "5.0") {
|
|
$mysql_status_result = `$connection_string -e "SHOW INNODB STATUS\\G"`;
|
|
} else {
|
|
$mysql_status_result = `$connection_string -e "SHOW ENGINE INNODB STATUS\\G"`;
|
|
}
|
|
|
|
# Process output of show innodb status
|
|
my @temp = split ("\n", $mysql_status_result);
|
|
|
|
# If we detect 'i/o waiting' lines then increment counter
|
|
$mysql_status_result = 0;
|
|
foreach (@temp) {
|
|
if ($_ =~ m/(.*)waiting for i\/o request(.*)/){
|
|
$mysql_status_result++;
|
|
}
|
|
}
|
|
}
|
|
|
|
unlink ($temp_file);
|
|
|
|
# If we want to retrieve active session substract 1 due to header
|
|
if ($show_parameter =~ /processlist/i) {
|
|
if ($mysql_status_result > 0){
|
|
$mysql_status_result--;
|
|
}
|
|
}
|
|
|
|
logger("[INFO] check_mysql_status executing: $show_parameter with result: " . $mysql_status_result);
|
|
|
|
return $mysql_status_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# is_numeric (arg)
|
|
#
|
|
# Return TRUE if given argument is numeric
|
|
# ----------------------------------------------------------------------
|
|
sub is_numeric($) {
|
|
my $val = $_[0];
|
|
|
|
if (!defined($val)){
|
|
return 0;
|
|
}
|
|
# Replace "," for "."
|
|
$val =~ s/\,/\./;
|
|
|
|
my $DIGITS = qr{ \d+ (?: [.] \d*)? | [.] \d+ }xms;
|
|
my $SIGN = qr{ [+-] }xms;
|
|
my $NUMBER = qr{ ($SIGN?) ($DIGITS) }xms;
|
|
if ( $val !~ /^${NUMBER}$/ ) {
|
|
return 0; #Non-numeric
|
|
} else {
|
|
return 1; #Numeric
|
|
}
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# eval_postcondition (result, operator, value)
|
|
#
|
|
# This function eval postcondition and return a boolean
|
|
# ----------------------------------------------------------------------
|
|
sub eval_postcondition($$$) {
|
|
my $result = $_[0];
|
|
my $operator = $_[1];
|
|
my $value = $_[2];
|
|
my $eval_postcondition_result = 0;
|
|
|
|
my $result_type = is_numeric($result);
|
|
|
|
logger("[INFO] Evaluating poscondition: $result $operator $value.");
|
|
|
|
# Numeric result
|
|
if ($result_type == 1) {
|
|
# Equal to
|
|
if ($operator =~ /==/) {
|
|
if (int($result) == int($value)) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# Not equal to
|
|
elsif ($operator =~ /!=/) {
|
|
|
|
if (int($result) != int($value)) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# Less than
|
|
elsif ($operator =~ /</) {
|
|
|
|
if (int($result) < int($value)) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# More than
|
|
elsif ($operator =~ />/) {
|
|
|
|
if (int($result) > int($value)) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
} else {
|
|
|
|
logger("[ERROR] Unknown operator in postcondition, please revise your configuration file.");
|
|
$eval_postcondition_result = 0;
|
|
|
|
}
|
|
} # Non numeric result
|
|
else {
|
|
|
|
my $result_value = sprintf("%s", $result);
|
|
my $string_value = sprintf("%s", $value);
|
|
|
|
# Equal to
|
|
if ($operator =~ /==/) {
|
|
|
|
if ($result_value =~ /$string_value/) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# Not equal to
|
|
elsif ($operator =~ /!=/) {
|
|
|
|
if ($result_value !~ /$string_value/) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# Less than
|
|
elsif ($operator =~ /</) {
|
|
|
|
if ($result_value lt $string_value) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
}# More than
|
|
elsif ($operator =~ />/) {
|
|
|
|
if ($result_value gt $string_value) {
|
|
|
|
$eval_postcondition_result = 1;
|
|
|
|
}
|
|
} else {
|
|
|
|
logger("[ERROR] Unknown operator in postcondition, please revise your configuration file.");
|
|
$eval_postcondition_result = 0;
|
|
|
|
}
|
|
}
|
|
|
|
return $eval_postcondition_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# eval_postcondition_array (Array result, operator, value)
|
|
#
|
|
# This function eval postcondition and return a boolean if some of the
|
|
# elements fulfill the condition
|
|
# ----------------------------------------------------------------------
|
|
sub eval_postcondition_array {
|
|
# This works
|
|
my $value = pop;
|
|
my $operator = pop;
|
|
my @result = @_;
|
|
|
|
my $eval_postcondition_array_result = 0;
|
|
my $return_postcondition_element = 0;
|
|
|
|
# Eval all array
|
|
foreach my $single_result (@result) {
|
|
|
|
$return_postcondition_element = 0;
|
|
|
|
$return_postcondition_element = eval_postcondition($single_result, $operator, $value);
|
|
|
|
if ($return_postcondition_element) {
|
|
$eval_postcondition_array_result = 1;
|
|
}
|
|
}
|
|
|
|
return $eval_postcondition_array_result;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# store_result_check(check_type, value)
|
|
#
|
|
# This function stores in a temporary file the last value of the check
|
|
# ----------------------------------------------------------------------
|
|
sub store_result_check($$) {
|
|
my $type = $_[0];
|
|
my $value = $_[1];
|
|
|
|
# Compose the temp filename
|
|
my $tmp_file = $plugin_setup{'conf_temp'} . '/mysql_check_' . $type . '.tmp';
|
|
|
|
# Try to open temp file
|
|
if (! open (TMP, "> $tmp_file")) {
|
|
logger("[ERROR] Error opening temp file: $tmp_file for write last check value: $type, $value");
|
|
return;
|
|
}
|
|
|
|
# Write las check value
|
|
print TMP $value;
|
|
close (TMP);
|
|
|
|
logger("[INFO] Saving last check value: $value of check: $type in file $tmp_file .");
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# process_delta_data(check_type, value)
|
|
#
|
|
# This function calculates delta value for the current check
|
|
# ----------------------------------------------------------------------
|
|
sub process_delta_data($$) {
|
|
my $type = $_[0];
|
|
my $value = $_[1];
|
|
my $buffer_line;
|
|
|
|
# Compose the temp filename
|
|
my $tmp_file = $plugin_setup{'conf_temp'} . '/mysql_check_' . $type . '.tmp';
|
|
|
|
# Collect info from temp file
|
|
# If it's not possible then return token for not print module
|
|
if (! open (TMP, "< $tmp_file")) {
|
|
return '::MYSQL _ NON EXEC';
|
|
}
|
|
|
|
while (<TMP>) {
|
|
$buffer_line = parse_dosline ($_);
|
|
}
|
|
|
|
my $process_delta_result = int($value) - int($buffer_line);
|
|
|
|
close (TMP);
|
|
|
|
# If delta value is negative then reset check last value
|
|
if ($process_delta_result < 0) {
|
|
logger("[INFO] Reset last value of check_" . $type . " due to negative value: " . $process_delta_result);
|
|
return '::MYSQL _ NON EXEC';
|
|
}
|
|
|
|
logger("[INFO] check_" . $type . " postprocessed by delta calculation: " . $process_delta_result);
|
|
|
|
return $process_delta_result;
|
|
}
|
|
|
|
###############################################################################
|
|
###############################################################################
|
|
######################## MAIN PROGRAM CODE ####################################
|
|
###############################################################################
|
|
###############################################################################
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Checks input parameter from command line (Conf file)
|
|
# ----------------------------------------------------------------------
|
|
my $log_init = 0;
|
|
|
|
# Load config file from command line
|
|
if ($#ARGV == -1){
|
|
print "I need at least one parameter: Complete path to external configuration file \n";
|
|
logger_begin("[ERROR] Path to configuration file it's needed");
|
|
|
|
# Logfile is initiated
|
|
$log_init = 1;
|
|
|
|
exit 0;
|
|
}
|
|
|
|
# Check for conf file
|
|
if ( ! -f $archivo_cfg ) {
|
|
printf "\n [ERROR] Cannot open configuration file at $archivo_cfg. \n\n";
|
|
|
|
if ($log_init == 1) {
|
|
logger("[ERROR] Cannot open configuration file at $archivo_cfg, please set permissions correctly.");
|
|
} else {
|
|
logger_begin("[ERROR] Cannot open configuration file at $archivo_cfg, please set permissions correctly.");
|
|
$log_init = 1;
|
|
}
|
|
|
|
print_module("MySQL_plugin_error", "generic_proc", 0, "Cannot open configuration file at $archivo_cfg, please set permissions correctly.");
|
|
exit 0;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Parse external configuration file
|
|
# ----------------------------------------------------------------------
|
|
load_external_setup ($archivo_cfg);
|
|
|
|
if ($log_init == 1){
|
|
|
|
logger("[INFO] Parsing config file $archivo_cfg.");
|
|
|
|
} else {
|
|
|
|
logger_begin("[INFO] Parsing config file $archivo_cfg.");
|
|
$log_init = 1;
|
|
|
|
}
|
|
|
|
parse_config;
|
|
|
|
=COMMENT
|
|
print Dumper(%plugin_setup);
|
|
print Dumper(@checks);
|
|
|
|
exit;
|
|
=cut
|
|
|
|
# ----------------------------------------------------------------------
|
|
# First check connection to MySQL
|
|
# ----------------------------------------------------------------------
|
|
my $result_connection = check_mysql_connection;
|
|
if ($result_connection == 0) {
|
|
logger ("[ERROR] Connection to MySQL error, abort monitoring.");
|
|
exit 0;
|
|
}
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Process each check
|
|
# ----------------------------------------------------------------------
|
|
my $result_check;
|
|
my $module_type;
|
|
my $module_status;
|
|
my @result_check;
|
|
my $performance_parameter;
|
|
foreach (@checks) {
|
|
|
|
# Don't asumme performance parameter
|
|
$performance_parameter = 0;
|
|
my $type = $_->{'type'};
|
|
my $postcondition_op = $_->{'postcondition_op'};
|
|
my $postcondition_val = $_->{'postcondition_val'};
|
|
my $postexecution = $_->{'postexecution'};
|
|
my $check_status = $_->{'status'};
|
|
my $check_show = $_->{'show'};
|
|
my $return_type = $_->{'return_type'};
|
|
my $check_name = $_->{'check_name'};
|
|
|
|
$result_check = 0;
|
|
# Process check (System parameters)
|
|
if ($_->{'type'} eq 'mysql_service') {
|
|
|
|
$result_check = check_mysql_service;
|
|
|
|
} elsif ($_->{'type'} eq 'mysql_memory') {
|
|
|
|
$result_check = check_mysql_memory;
|
|
|
|
} elsif ($_->{'type'} eq 'mysql_cpu') {
|
|
|
|
$result_check = check_mysql_cpu;
|
|
|
|
} elsif ($_->{'type'} eq 'system_timewait') {
|
|
|
|
$result_check = check_system_timewait;
|
|
|
|
} elsif ($_->{'type'} eq 'system_diskusage') {
|
|
|
|
$result_check = check_system_diskusage;
|
|
|
|
} elsif ($_->{'type'} eq 'mysql_ibdata1') {
|
|
|
|
$result_check = check_mysql_ibdata1;
|
|
|
|
} elsif ($_->{'type'} eq 'mysql_connection') {
|
|
|
|
$result_check = check_mysql_connection;
|
|
|
|
} elsif ($_->{'type'} eq 'mysql_logs') {
|
|
|
|
@result_check = check_mysql_logs($_->{'module_type'});
|
|
|
|
}
|
|
# Process check (Perfomance parameters)
|
|
elsif ($_->{'type'} eq 'status') {
|
|
|
|
# This is a performance parameter
|
|
$performance_parameter = 1;
|
|
$result_check = check_mysql_status($_->{"show"});
|
|
|
|
}
|
|
# Process check (Open SQL interface)
|
|
elsif ($_->{'type'} eq 'sql') {
|
|
|
|
$performance_parameter = 1;
|
|
$result_check = check_mysql_status($_->{'type'}, $_->{"sql"}, $_->{'check_schema'});
|
|
|
|
}
|
|
# Process check (Query Innodb status)
|
|
elsif ($_->{'type'} eq 'innodb') {
|
|
|
|
$result_check = check_mysql_status($_->{'type'}, $_->{"query"});
|
|
|
|
}else {
|
|
|
|
logger("[INFO] Check block with invalid type, discart it. Please revise your configuration file.");
|
|
$result_check = 0;
|
|
|
|
}
|
|
|
|
# Use results
|
|
if (($_->{'type'} ne 'unknown')) {
|
|
|
|
# Prints module ('mysql_logs' check prints it's module inside check_mysql_logs function)
|
|
if ($_->{'type'} ne 'mysql_logs') {
|
|
|
|
# Evalue module type
|
|
$module_type = $_->{'module_type'};
|
|
|
|
# 'mysql_service' and 'mysql_connection' has always generic_proc type
|
|
if (($_->{'type'} eq 'mysql_service') or ($type eq 'mysql_connection')) {
|
|
|
|
$module_type = 'generic_proc';
|
|
|
|
}# By default type is generic_data
|
|
else {
|
|
|
|
$module_type = 'generic_data';
|
|
|
|
}
|
|
|
|
my $last_result_check = $result_check;
|
|
# If where are dealing with a performance parameter then look at return_type value
|
|
if ($performance_parameter and defined($_->{'return_type'})) {
|
|
|
|
if ($_->{'return_type'} eq 'data_delta') {
|
|
|
|
$result_check = process_delta_data($_->{'type'} . '_' . $_->{'show'}, $result_check);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Store result_check in temp file for delta postprocess
|
|
if ($performance_parameter) {
|
|
|
|
store_result_check($type . '_' . $check_show, $last_result_check);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
# Postcondition ('mysql_logs' type will have an array like result)
|
|
my $exec_postexecution = 0;
|
|
my $result_check_test = sprintf("%s", $result_check);
|
|
if (($type eq 'mysql_logs') and ($result_check_test ne '::MYSQL _ NON EXEC')) {
|
|
|
|
# if (defined($postcondition_op) and defined($postcondition_val)) {
|
|
|
|
# $exec_postexecution = eval_postcondition_array(@result_check, $postcondition_op, $postcondition_val);
|
|
|
|
# }
|
|
|
|
# If data has been returned, exec postcommand
|
|
if (@result_check) {
|
|
$exec_postexecution = 1;
|
|
}
|
|
|
|
}# Postcondition (other check types)
|
|
elsif (defined($postcondition_op) and defined($postcondition_val) and ($result_check_test ne '::MYSQL _ NON EXEC')) {
|
|
|
|
$exec_postexecution = eval_postcondition($result_check, $postcondition_op, $postcondition_val);
|
|
|
|
}
|
|
|
|
# If postcondition is not fulfilled then don't assign status to module
|
|
if (!$exec_postexecution) {
|
|
$check_status = 'NORMAL';
|
|
}
|
|
|
|
# Prints module ('mysql_logs' check prints it's module inside check_mysql_logs function)
|
|
if ($type ne 'mysql_logs') {
|
|
if ($result_check_test ne '::MYSQL _ NON EXEC') {
|
|
# Prints module
|
|
if ($type eq 'status') {
|
|
print_module("MySQL_" . $type . '_' . $check_show, $module_type, $result_check, '', $check_status);
|
|
} else {
|
|
if (defined($check_name)) {
|
|
print_module("MySQL_" . $type . "_" . $check_name, $module_type, $result_check, '', $check_status);
|
|
} else {
|
|
print_module("MySQL_" . $type, $module_type, $result_check, '', $check_status);
|
|
}
|
|
}
|
|
} else {
|
|
logger("[INFO] First execution of delta value for check $type, ignoring.");
|
|
}
|
|
}
|
|
|
|
# Exec command
|
|
if ($exec_postexecution) {
|
|
|
|
if (defined($postexecution)) {
|
|
|
|
logger("[INFO] Executing postexecution command: " . $postexecution);
|
|
if ($postexecution =~ /\_DATA\_/i) {
|
|
my $round_data = ceil ($result_check);
|
|
|
|
logger("[INFO] Detected macro _DATA_ in postexecution command, replacing with: $result_check");
|
|
$postexecution =~ s/\_DATA\_/$round_data/;
|
|
}
|
|
my $command_output = `$postexecution`;
|
|
logger("[INFO] Postexecution command result: " . $command_output);
|
|
|
|
}
|
|
}
|
|
|
|
} # type ne 'unknown'
|
|
}
|