#!/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 use lib '/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 () { $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 "\n"; print "$MODULE_NAME\n"; print "$MODULE_TYPE\n"; print "\n"; print "\n"; if (defined($MODULE_SEVERITY)) { print "$MODULE_SEVERITY\n"; } else { print "NORMAL\n"; } print "\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 () { 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 ($_ =~ /<\/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; } } 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 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 () { $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' }