[monitoring-plugins] Refactor check_mysql
Lorenz Kästle
git at monitoring-plugins.org
Tue Mar 11 13:40:12 CET 2025
Module: monitoring-plugins
Branch: master
Commit: 3143b5217cf1c71a085e6c4c7d22a5b699c4ff07
Author: Lorenz Kästle <12514511+RincewindsHat at users.noreply.github.com>
Date: Tue Mar 11 13:22:13 2025 +0100
URL: https://www.monitoring-plugins.org/repositories/monitoring-plugins/commit/?id=3143b521
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(-)
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 at monitoring-plugins.org";
#include "utils.h"
#include "utils_base.h"
#include "netutils.h"
+#include "check_mysql.d/config.h"
#include <mysql.h>
#include <mysqld_error.h>
#include <errmsg.h>
-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 <stddef.h>
+#include <mysql.h>
+
+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;
+}
More information about the Commits
mailing list