From 3143b5217cf1c71a085e6c4c7d22a5b699c4ff07 Mon Sep 17 00:00:00 2001 From: Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> Date: Tue, 11 Mar 2025 13:22:13 +0100 Subject: Refactor check_mysql --- plugins/Makefile.am | 1 + plugins/check_mysql.c | 217 +++++++++++++++++++---------------------- plugins/check_mysql.d/config.h | 58 +++++++++++ 3 files changed, 160 insertions(+), 116 deletions(-) create mode 100644 plugins/check_mysql.d/config.h (limited to 'plugins') diff --git a/plugins/Makefile.am b/plugins/Makefile.am index 06958849..9449f051 100644 --- a/plugins/Makefile.am +++ b/plugins/Makefile.am @@ -60,6 +60,7 @@ EXTRA_DIST = t \ check_apt.d \ check_by_ssh.d \ check_smtp.d \ + check_mysql.d \ check_dig.d \ check_cluster.d \ check_fping.d diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c index 2b6cfeaf..ca3422b5 100644 --- a/plugins/check_mysql.c +++ b/plugins/check_mysql.c @@ -40,32 +40,14 @@ const char *email = "devel@monitoring-plugins.org"; #include "utils.h" #include "utils_base.h" #include "netutils.h" +#include "check_mysql.d/config.h" #include #include #include -static char *db_user = NULL; -static char *db_host = NULL; -static char *db_socket = NULL; -static char *db_pass = NULL; -static char *db = NULL; -static char *ca_cert = NULL; -static char *ca_dir = NULL; -static char *cert = NULL; -static char *key = NULL; -static char *ciphers = NULL; -static bool ssl = false; -static char *opt_file = NULL; -static char *opt_group = NULL; -static unsigned int db_port = MYSQL_PORT; -static bool check_replica = false; -static bool ignore_auth = false; static int verbose = 0; -static double warning_time = 0; -static double critical_time = 0; - #define LENGTH_METRIC_UNIT 6 static const char *metric_unit[LENGTH_METRIC_UNIT] = { "Open_files", "Open_tables", "Qcache_free_memory", "Qcache_queries_in_cache", "Threads_connected", "Threads_running"}; @@ -78,28 +60,16 @@ static const char *metric_counter[LENGTH_METRIC_COUNTER] = { #define MYSQLDUMP_THREADS_QUERY \ "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'" -static thresholds *my_threshold = NULL; - -static int process_arguments(int, char **); -static int validate_arguments(void); +typedef struct { + int errorcode; + check_mysql_config config; +} check_mysql_config_wrapper; +static check_mysql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); +static check_mysql_config_wrapper validate_arguments(check_mysql_config_wrapper /*config_wrapper*/); static void print_help(void); void print_usage(void); int main(int argc, char **argv) { - - MYSQL mysql; - MYSQL_RES *res; - MYSQL_ROW row; - - /* should be status */ - - char *result = NULL; - char *error = NULL; - char replica_result[REPLICA_RESULTSIZE] = {0}; - char *perf; - - perf = strdup(""); - setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); @@ -107,36 +77,43 @@ int main(int argc, char **argv) { /* Parse extra opts if any */ argv = np_extra_opts(&argc, argv, progname); - if (process_arguments(argc, argv) == ERROR) { + check_mysql_config_wrapper tmp_config = process_arguments(argc, argv); + if (tmp_config.errorcode == ERROR) { usage4(_("Could not parse arguments")); } + const check_mysql_config config = tmp_config.config; + + MYSQL mysql; /* initialize mysql */ mysql_init(&mysql); - if (opt_file != NULL) { - mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, opt_file); + if (config.opt_file != NULL) { + mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, config.opt_file); } - if (opt_group != NULL) { - mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, opt_group); + if (config.opt_group != NULL) { + mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, config.opt_group); } else { mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client"); } - if (ssl) { - mysql_ssl_set(&mysql, key, cert, ca_cert, ca_dir, ciphers); + if (config.ssl) { + mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, config.ciphers); } /* establish a connection to the server and error checking */ - if (!mysql_real_connect(&mysql, db_host, db_user, db_pass, db, db_port, db_socket, 0)) { + if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) { /* Depending on internally-selected auth plugin MySQL might return */ /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */ /* Semantically these errors are the same. */ - if (ignore_auth && (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { + if (config.ignore_auth && + (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), mysql_get_proto_info(&mysql)); mysql_close(&mysql); return STATE_OK; - } else if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { + } + + if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { die(STATE_WARNING, "%s\n", mysql_error(&mysql)); } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { die(STATE_WARNING, "%s\n", mysql_error(&mysql)); @@ -152,7 +129,7 @@ int main(int argc, char **argv) { } /* get the server stats */ - result = strdup(mysql_stat(&mysql)); + char *result = strdup(mysql_stat(&mysql)); /* error checking once more */ if (mysql_error(&mysql)) { @@ -165,6 +142,10 @@ int main(int argc, char **argv) { } } + char *perf = strdup(""); + char *error = NULL; + MYSQL_RES *res; + MYSQL_ROW row; /* try to fetch some perf data */ if (mysql_query(&mysql, "show global status") == 0) { if ((res = mysql_store_result(&mysql)) == NULL) { @@ -174,15 +155,13 @@ int main(int argc, char **argv) { } while ((row = mysql_fetch_row(res)) != NULL) { - int i; - - for (i = 0; i < LENGTH_METRIC_UNIT; i++) { + for (int i = 0; i < LENGTH_METRIC_UNIT; i++) { if (strcmp(row[0], metric_unit[i]) == 0) { xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, 0, false, 0)); continue; } } - for (i = 0; i < LENGTH_METRIC_COUNTER; i++) { + for (int i = 0; i < LENGTH_METRIC_COUNTER; i++) { if (strcmp(row[0], metric_counter[i]) == 0) { xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, false, 0, false, 0)); continue; @@ -195,8 +174,8 @@ int main(int argc, char **argv) { } } - if (check_replica) { - + char replica_result[REPLICA_RESULTSIZE] = {0}; + if (config.check_replica) { // Detect which version we are, on older version // "show slave status" should work, on newer ones // "show replica status" @@ -283,12 +262,14 @@ int main(int argc, char **argv) { } else { /* mysql 4.x.x and mysql 5.x.x */ - int replica_io_field = -1, replica_sql_field = -1, seconds_behind_field = -1, i, num_fields; + int replica_io_field = -1; + int replica_sql_field = -1; + int seconds_behind_field = -1; + int num_fields; MYSQL_FIELD *fields; - num_fields = mysql_num_fields(res); fields = mysql_fetch_fields(res); - for (i = 0; i < num_fields; i++) { + for (int i = 0; i < num_fields; i++) { if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { replica_io_field = i; continue; @@ -353,11 +334,11 @@ int main(int argc, char **argv) { double value = atof(row[seconds_behind_field]); int status; - status = get_status(value, my_threshold); + status = get_status(value, config.my_threshold); xasprintf(&perf, "%s %s", perf, - fperfdata("seconds behind master", value, "s", true, (double)warning_time, true, (double)critical_time, false, 0, - false, 0)); + fperfdata("seconds behind master", value, "s", true, (double)config.warning_time, true, + (double)config.critical_time, false, 0, false, 0)); if (status == STATE_WARNING) { printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf); @@ -377,7 +358,7 @@ int main(int argc, char **argv) { mysql_close(&mysql); /* print out the result of stats */ - if (check_replica) { + if (config.check_replica) { printf("%s %s|%s\n", result, replica_result, perf); } else { printf("%s|%s\n", result, perf); @@ -389,12 +370,7 @@ int main(int argc, char **argv) { #define CHECK_REPLICA_OPT CHAR_MAX + 1 /* process command-line arguments */ -int process_arguments(int argc, char **argv) { - int c; - char *warning = NULL; - char *critical = NULL; - - int option = 0; +check_mysql_config_wrapper process_arguments(int argc, char **argv) { static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, {"socket", required_argument, 0, 's'}, {"database", required_argument, 0, 'd'}, @@ -419,56 +395,66 @@ int process_arguments(int argc, char **argv) { {"ciphers", required_argument, 0, 'L'}, {0, 0, 0, 0}}; + check_mysql_config_wrapper result = { + .errorcode = OK, + .config = check_mysql_config_init(), + }; + if (argc < 1) { - return ERROR; + result.errorcode = ERROR; + return result; } - while (1) { - c = getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); + char *warning = NULL; + char *critical = NULL; + + int option = 0; + while (true) { + int option_index = getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); - if (c == -1 || c == EOF) { + if (option_index == -1 || option_index == EOF) { break; } - switch (c) { + switch (option_index) { case 'H': /* hostname */ if (is_host(optarg)) { - db_host = optarg; + result.config.db_host = optarg; } else if (*optarg == '/') { - db_socket = optarg; + result.config.db_socket = optarg; } else { usage2(_("Invalid hostname/address"), optarg); } break; case 's': /* socket */ - db_socket = optarg; + result.config.db_socket = optarg; break; case 'd': /* database */ - db = optarg; + result.config.db = optarg; break; case 'l': - ssl = true; + result.config.ssl = true; break; case 'C': - ca_cert = optarg; + result.config.ca_cert = optarg; break; case 'a': - cert = optarg; + result.config.cert = optarg; break; case 'k': - key = optarg; + result.config.key = optarg; break; case 'D': - ca_dir = optarg; + result.config.ca_dir = optarg; break; case 'L': - ciphers = optarg; + result.config.ciphers = optarg; break; case 'u': /* username */ - db_user = optarg; + result.config.db_user = optarg; break; case 'p': /* authentication information: password */ - db_pass = strdup(optarg); + result.config.db_pass = strdup(optarg); /* Delete the password from process list */ while (*optarg != '\0') { @@ -477,28 +463,28 @@ int process_arguments(int argc, char **argv) { } break; case 'f': /* client options file */ - opt_file = optarg; + result.config.opt_file = optarg; break; case 'g': /* client options group */ - opt_group = optarg; + result.config.opt_group = optarg; break; case 'P': /* critical time threshold */ - db_port = atoi(optarg); + result.config.db_port = atoi(optarg); break; case 'S': case CHECK_REPLICA_OPT: - check_replica = true; /* check-slave */ + result.config.check_replica = true; /* check-slave */ break; case 'n': - ignore_auth = true; /* ignore-auth */ + result.config.ignore_auth = true; /* ignore-auth */ break; case 'w': warning = optarg; - warning_time = strtod(warning, NULL); + result.config.warning_time = strtod(warning, NULL); break; case 'c': critical = optarg; - critical_time = strtod(critical, NULL); + result.config.critical_time = strtod(critical, NULL); break; case 'V': /* version */ print_revision(progname, NP_VERSION); @@ -514,48 +500,47 @@ int process_arguments(int argc, char **argv) { } } - c = optind; - - set_thresholds(&my_threshold, warning, critical); + int index = optind; - while (argc > c) { + set_thresholds(&result.config.my_threshold, warning, critical); - if (db_host == NULL) { - if (is_host(argv[c])) { - db_host = argv[c++]; + while (argc > index) { + if (result.config.db_host == NULL) { + if (is_host(argv[index])) { + result.config.db_host = argv[index++]; } else { - usage2(_("Invalid hostname/address"), argv[c]); + usage2(_("Invalid hostname/address"), argv[index]); } - } else if (db_user == NULL) { - db_user = argv[c++]; - } else if (db_pass == NULL) { - db_pass = argv[c++]; - } else if (db == NULL) { - db = argv[c++]; - } else if (is_intnonneg(argv[c])) { - db_port = atoi(argv[c++]); + } else if (result.config.db_user == NULL) { + result.config.db_user = argv[index++]; + } else if (result.config.db_pass == NULL) { + result.config.db_pass = argv[index++]; + } else if (result.config.db == NULL) { + result.config.db = argv[index++]; + } else if (is_intnonneg(argv[index])) { + result.config.db_port = atoi(argv[index++]); } else { break; } } - return validate_arguments(); + return validate_arguments(result); } -int validate_arguments(void) { - if (db_user == NULL) { - db_user = strdup(""); +check_mysql_config_wrapper validate_arguments(check_mysql_config_wrapper config_wrapper) { + if (config_wrapper.config.db_user == NULL) { + config_wrapper.config.db_user = strdup(""); } - if (db_host == NULL) { - db_host = strdup(""); + if (config_wrapper.config.db_host == NULL) { + config_wrapper.config.db_host = strdup(""); } - if (db == NULL) { - db = strdup(""); + if (config_wrapper.config.db == NULL) { + config_wrapper.config.db = strdup(""); } - return OK; + return config_wrapper; } void print_help(void) { diff --git a/plugins/check_mysql.d/config.h b/plugins/check_mysql.d/config.h new file mode 100644 index 00000000..71ddbe8d --- /dev/null +++ b/plugins/check_mysql.d/config.h @@ -0,0 +1,58 @@ +#pragma once + +#include "../../config.h" +#include "thresholds.h" +#include +#include + +typedef struct { + char *db_host; + unsigned int db_port; + char *db_user; + char *db_socket; + char *db_pass; + char *db; + char *ca_cert; + char *ca_dir; + char *cert; + char *key; + char *ciphers; + bool ssl; + char *opt_file; + char *opt_group; + + bool check_replica; + bool ignore_auth; + + double warning_time; + double critical_time; + thresholds *my_threshold; + +} check_mysql_config; + +check_mysql_config check_mysql_config_init() { + check_mysql_config tmp = { + .db_host = NULL, + .db_port = MYSQL_PORT, + .db = NULL, + .db_pass = NULL, + .db_socket = NULL, + .db_user = NULL, + .ca_cert = NULL, + .ca_dir = NULL, + .cert = NULL, + .key = NULL, + .ciphers = NULL, + .ssl = false, + .opt_file = NULL, + .opt_group = NULL, + + .check_replica = false, + .ignore_auth = false, + + .warning_time = 0, + .critical_time = 0, + .my_threshold = NULL, + }; + return tmp; +} -- cgit v1.2.3-74-g34f1