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'
|
|
}
|