summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/Makefile.am1
-rw-r--r--plugins/check_mysql.c217
-rw-r--r--plugins/check_mysql.d/config.h58
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 \
60 check_apt.d \ 60 check_apt.d \
61 check_by_ssh.d \ 61 check_by_ssh.d \
62 check_smtp.d \ 62 check_smtp.d \
63 check_mysql.d \
63 check_dig.d \ 64 check_dig.d \
64 check_cluster.d \ 65 check_cluster.d \
65 check_fping.d 66 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";
40#include "utils.h" 40#include "utils.h"
41#include "utils_base.h" 41#include "utils_base.h"
42#include "netutils.h" 42#include "netutils.h"
43#include "check_mysql.d/config.h"
43 44
44#include <mysql.h> 45#include <mysql.h>
45#include <mysqld_error.h> 46#include <mysqld_error.h>
46#include <errmsg.h> 47#include <errmsg.h>
47 48
48static char *db_user = NULL;
49static char *db_host = NULL;
50static char *db_socket = NULL;
51static char *db_pass = NULL;
52static char *db = NULL;
53static char *ca_cert = NULL;
54static char *ca_dir = NULL;
55static char *cert = NULL;
56static char *key = NULL;
57static char *ciphers = NULL;
58static bool ssl = false;
59static char *opt_file = NULL;
60static char *opt_group = NULL;
61static unsigned int db_port = MYSQL_PORT;
62static bool check_replica = false;
63static bool ignore_auth = false;
64static int verbose = 0; 49static int verbose = 0;
65 50
66static double warning_time = 0;
67static double critical_time = 0;
68
69#define LENGTH_METRIC_UNIT 6 51#define LENGTH_METRIC_UNIT 6
70static const char *metric_unit[LENGTH_METRIC_UNIT] = { 52static const char *metric_unit[LENGTH_METRIC_UNIT] = {
71 "Open_files", "Open_tables", "Qcache_free_memory", "Qcache_queries_in_cache", "Threads_connected", "Threads_running"}; 53 "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] = {
78#define MYSQLDUMP_THREADS_QUERY \ 60#define MYSQLDUMP_THREADS_QUERY \
79 "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'" 61 "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'"
80 62
81static thresholds *my_threshold = NULL; 63typedef struct {
82 64 int errorcode;
83static int process_arguments(int, char **); 65 check_mysql_config config;
84static int validate_arguments(void); 66} check_mysql_config_wrapper;
67static check_mysql_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
68static check_mysql_config_wrapper validate_arguments(check_mysql_config_wrapper /*config_wrapper*/);
85static void print_help(void); 69static void print_help(void);
86void print_usage(void); 70void print_usage(void);
87 71
88int main(int argc, char **argv) { 72int main(int argc, char **argv) {
89
90 MYSQL mysql;
91 MYSQL_RES *res;
92 MYSQL_ROW row;
93
94 /* should be status */
95
96 char *result = NULL;
97 char *error = NULL;
98 char replica_result[REPLICA_RESULTSIZE] = {0};
99 char *perf;
100
101 perf = strdup("");
102
103 setlocale(LC_ALL, ""); 73 setlocale(LC_ALL, "");
104 bindtextdomain(PACKAGE, LOCALEDIR); 74 bindtextdomain(PACKAGE, LOCALEDIR);
105 textdomain(PACKAGE); 75 textdomain(PACKAGE);
@@ -107,36 +77,43 @@ int main(int argc, char **argv) {
107 /* Parse extra opts if any */ 77 /* Parse extra opts if any */
108 argv = np_extra_opts(&argc, argv, progname); 78 argv = np_extra_opts(&argc, argv, progname);
109 79
110 if (process_arguments(argc, argv) == ERROR) { 80 check_mysql_config_wrapper tmp_config = process_arguments(argc, argv);
81 if (tmp_config.errorcode == ERROR) {
111 usage4(_("Could not parse arguments")); 82 usage4(_("Could not parse arguments"));
112 } 83 }
113 84
85 const check_mysql_config config = tmp_config.config;
86
87 MYSQL mysql;
114 /* initialize mysql */ 88 /* initialize mysql */
115 mysql_init(&mysql); 89 mysql_init(&mysql);
116 90
117 if (opt_file != NULL) { 91 if (config.opt_file != NULL) {
118 mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, opt_file); 92 mysql_options(&mysql, MYSQL_READ_DEFAULT_FILE, config.opt_file);
119 } 93 }
120 94
121 if (opt_group != NULL) { 95 if (config.opt_group != NULL) {
122 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, opt_group); 96 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, config.opt_group);
123 } else { 97 } else {
124 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client"); 98 mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client");
125 } 99 }
126 100
127 if (ssl) { 101 if (config.ssl) {
128 mysql_ssl_set(&mysql, key, cert, ca_cert, ca_dir, ciphers); 102 mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, config.ciphers);
129 } 103 }
130 /* establish a connection to the server and error checking */ 104 /* establish a connection to the server and error checking */
131 if (!mysql_real_connect(&mysql, db_host, db_user, db_pass, db, db_port, db_socket, 0)) { 105 if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) {
132 /* Depending on internally-selected auth plugin MySQL might return */ 106 /* Depending on internally-selected auth plugin MySQL might return */
133 /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */ 107 /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */
134 /* Semantically these errors are the same. */ 108 /* Semantically these errors are the same. */
135 if (ignore_auth && (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { 109 if (config.ignore_auth &&
110 (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) {
136 printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), mysql_get_proto_info(&mysql)); 111 printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), mysql_get_proto_info(&mysql));
137 mysql_close(&mysql); 112 mysql_close(&mysql);
138 return STATE_OK; 113 return STATE_OK;
139 } else if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { 114 }
115
116 if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) {
140 die(STATE_WARNING, "%s\n", mysql_error(&mysql)); 117 die(STATE_WARNING, "%s\n", mysql_error(&mysql));
141 } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { 118 } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) {
142 die(STATE_WARNING, "%s\n", mysql_error(&mysql)); 119 die(STATE_WARNING, "%s\n", mysql_error(&mysql));
@@ -152,7 +129,7 @@ int main(int argc, char **argv) {
152 } 129 }
153 130
154 /* get the server stats */ 131 /* get the server stats */
155 result = strdup(mysql_stat(&mysql)); 132 char *result = strdup(mysql_stat(&mysql));
156 133
157 /* error checking once more */ 134 /* error checking once more */
158 if (mysql_error(&mysql)) { 135 if (mysql_error(&mysql)) {
@@ -165,6 +142,10 @@ int main(int argc, char **argv) {
165 } 142 }
166 } 143 }
167 144
145 char *perf = strdup("");
146 char *error = NULL;
147 MYSQL_RES *res;
148 MYSQL_ROW row;
168 /* try to fetch some perf data */ 149 /* try to fetch some perf data */
169 if (mysql_query(&mysql, "show global status") == 0) { 150 if (mysql_query(&mysql, "show global status") == 0) {
170 if ((res = mysql_store_result(&mysql)) == NULL) { 151 if ((res = mysql_store_result(&mysql)) == NULL) {
@@ -174,15 +155,13 @@ int main(int argc, char **argv) {
174 } 155 }
175 156
176 while ((row = mysql_fetch_row(res)) != NULL) { 157 while ((row = mysql_fetch_row(res)) != NULL) {
177 int i; 158 for (int i = 0; i < LENGTH_METRIC_UNIT; i++) {
178
179 for (i = 0; i < LENGTH_METRIC_UNIT; i++) {
180 if (strcmp(row[0], metric_unit[i]) == 0) { 159 if (strcmp(row[0], metric_unit[i]) == 0) {
181 xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, 0, false, 0)); 160 xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, 0, false, 0));
182 continue; 161 continue;
183 } 162 }
184 } 163 }
185 for (i = 0; i < LENGTH_METRIC_COUNTER; i++) { 164 for (int i = 0; i < LENGTH_METRIC_COUNTER; i++) {
186 if (strcmp(row[0], metric_counter[i]) == 0) { 165 if (strcmp(row[0], metric_counter[i]) == 0) {
187 xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, false, 0, false, 0)); 166 xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, false, 0, false, 0));
188 continue; 167 continue;
@@ -195,8 +174,8 @@ int main(int argc, char **argv) {
195 } 174 }
196 } 175 }
197 176
198 if (check_replica) { 177 char replica_result[REPLICA_RESULTSIZE] = {0};
199 178 if (config.check_replica) {
200 // Detect which version we are, on older version 179 // Detect which version we are, on older version
201 // "show slave status" should work, on newer ones 180 // "show slave status" should work, on newer ones
202 // "show replica status" 181 // "show replica status"
@@ -283,12 +262,14 @@ int main(int argc, char **argv) {
283 262
284 } else { 263 } else {
285 /* mysql 4.x.x and mysql 5.x.x */ 264 /* mysql 4.x.x and mysql 5.x.x */
286 int replica_io_field = -1, replica_sql_field = -1, seconds_behind_field = -1, i, num_fields; 265 int replica_io_field = -1;
266 int replica_sql_field = -1;
267 int seconds_behind_field = -1;
268 int num_fields;
287 MYSQL_FIELD *fields; 269 MYSQL_FIELD *fields;
288
289 num_fields = mysql_num_fields(res); 270 num_fields = mysql_num_fields(res);
290 fields = mysql_fetch_fields(res); 271 fields = mysql_fetch_fields(res);
291 for (i = 0; i < num_fields; i++) { 272 for (int i = 0; i < num_fields; i++) {
292 if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { 273 if (strcmp(fields[i].name, "Slave_IO_Running") == 0) {
293 replica_io_field = i; 274 replica_io_field = i;
294 continue; 275 continue;
@@ -353,11 +334,11 @@ int main(int argc, char **argv) {
353 double value = atof(row[seconds_behind_field]); 334 double value = atof(row[seconds_behind_field]);
354 int status; 335 int status;
355 336
356 status = get_status(value, my_threshold); 337 status = get_status(value, config.my_threshold);
357 338
358 xasprintf(&perf, "%s %s", perf, 339 xasprintf(&perf, "%s %s", perf,
359 fperfdata("seconds behind master", value, "s", true, (double)warning_time, true, (double)critical_time, false, 0, 340 fperfdata("seconds behind master", value, "s", true, (double)config.warning_time, true,
360 false, 0)); 341 (double)config.critical_time, false, 0, false, 0));
361 342
362 if (status == STATE_WARNING) { 343 if (status == STATE_WARNING) {
363 printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf); 344 printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf);
@@ -377,7 +358,7 @@ int main(int argc, char **argv) {
377 mysql_close(&mysql); 358 mysql_close(&mysql);
378 359
379 /* print out the result of stats */ 360 /* print out the result of stats */
380 if (check_replica) { 361 if (config.check_replica) {
381 printf("%s %s|%s\n", result, replica_result, perf); 362 printf("%s %s|%s\n", result, replica_result, perf);
382 } else { 363 } else {
383 printf("%s|%s\n", result, perf); 364 printf("%s|%s\n", result, perf);
@@ -389,12 +370,7 @@ int main(int argc, char **argv) {
389#define CHECK_REPLICA_OPT CHAR_MAX + 1 370#define CHECK_REPLICA_OPT CHAR_MAX + 1
390 371
391/* process command-line arguments */ 372/* process command-line arguments */
392int process_arguments(int argc, char **argv) { 373check_mysql_config_wrapper process_arguments(int argc, char **argv) {
393 int c;
394 char *warning = NULL;
395 char *critical = NULL;
396
397 int option = 0;
398 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, 374 static struct option longopts[] = {{"hostname", required_argument, 0, 'H'},
399 {"socket", required_argument, 0, 's'}, 375 {"socket", required_argument, 0, 's'},
400 {"database", required_argument, 0, 'd'}, 376 {"database", required_argument, 0, 'd'},
@@ -419,56 +395,66 @@ int process_arguments(int argc, char **argv) {
419 {"ciphers", required_argument, 0, 'L'}, 395 {"ciphers", required_argument, 0, 'L'},
420 {0, 0, 0, 0}}; 396 {0, 0, 0, 0}};
421 397
398 check_mysql_config_wrapper result = {
399 .errorcode = OK,
400 .config = check_mysql_config_init(),
401 };
402
422 if (argc < 1) { 403 if (argc < 1) {
423 return ERROR; 404 result.errorcode = ERROR;
405 return result;
424 } 406 }
425 407
426 while (1) { 408 char *warning = NULL;
427 c = getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); 409 char *critical = NULL;
410
411 int option = 0;
412 while (true) {
413 int option_index = getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option);
428 414
429 if (c == -1 || c == EOF) { 415 if (option_index == -1 || option_index == EOF) {
430 break; 416 break;
431 } 417 }
432 418
433 switch (c) { 419 switch (option_index) {
434 case 'H': /* hostname */ 420 case 'H': /* hostname */
435 if (is_host(optarg)) { 421 if (is_host(optarg)) {
436 db_host = optarg; 422 result.config.db_host = optarg;
437 } else if (*optarg == '/') { 423 } else if (*optarg == '/') {
438 db_socket = optarg; 424 result.config.db_socket = optarg;
439 } else { 425 } else {
440 usage2(_("Invalid hostname/address"), optarg); 426 usage2(_("Invalid hostname/address"), optarg);
441 } 427 }
442 break; 428 break;
443 case 's': /* socket */ 429 case 's': /* socket */
444 db_socket = optarg; 430 result.config.db_socket = optarg;
445 break; 431 break;
446 case 'd': /* database */ 432 case 'd': /* database */
447 db = optarg; 433 result.config.db = optarg;
448 break; 434 break;
449 case 'l': 435 case 'l':
450 ssl = true; 436 result.config.ssl = true;
451 break; 437 break;
452 case 'C': 438 case 'C':
453 ca_cert = optarg; 439 result.config.ca_cert = optarg;
454 break; 440 break;
455 case 'a': 441 case 'a':
456 cert = optarg; 442 result.config.cert = optarg;
457 break; 443 break;
458 case 'k': 444 case 'k':
459 key = optarg; 445 result.config.key = optarg;
460 break; 446 break;
461 case 'D': 447 case 'D':
462 ca_dir = optarg; 448 result.config.ca_dir = optarg;
463 break; 449 break;
464 case 'L': 450 case 'L':
465 ciphers = optarg; 451 result.config.ciphers = optarg;
466 break; 452 break;
467 case 'u': /* username */ 453 case 'u': /* username */
468 db_user = optarg; 454 result.config.db_user = optarg;
469 break; 455 break;
470 case 'p': /* authentication information: password */ 456 case 'p': /* authentication information: password */
471 db_pass = strdup(optarg); 457 result.config.db_pass = strdup(optarg);
472 458
473 /* Delete the password from process list */ 459 /* Delete the password from process list */
474 while (*optarg != '\0') { 460 while (*optarg != '\0') {
@@ -477,28 +463,28 @@ int process_arguments(int argc, char **argv) {
477 } 463 }
478 break; 464 break;
479 case 'f': /* client options file */ 465 case 'f': /* client options file */
480 opt_file = optarg; 466 result.config.opt_file = optarg;
481 break; 467 break;
482 case 'g': /* client options group */ 468 case 'g': /* client options group */
483 opt_group = optarg; 469 result.config.opt_group = optarg;
484 break; 470 break;
485 case 'P': /* critical time threshold */ 471 case 'P': /* critical time threshold */
486 db_port = atoi(optarg); 472 result.config.db_port = atoi(optarg);
487 break; 473 break;
488 case 'S': 474 case 'S':
489 case CHECK_REPLICA_OPT: 475 case CHECK_REPLICA_OPT:
490 check_replica = true; /* check-slave */ 476 result.config.check_replica = true; /* check-slave */
491 break; 477 break;
492 case 'n': 478 case 'n':
493 ignore_auth = true; /* ignore-auth */ 479 result.config.ignore_auth = true; /* ignore-auth */
494 break; 480 break;
495 case 'w': 481 case 'w':
496 warning = optarg; 482 warning = optarg;
497 warning_time = strtod(warning, NULL); 483 result.config.warning_time = strtod(warning, NULL);
498 break; 484 break;
499 case 'c': 485 case 'c':
500 critical = optarg; 486 critical = optarg;
501 critical_time = strtod(critical, NULL); 487 result.config.critical_time = strtod(critical, NULL);
502 break; 488 break;
503 case 'V': /* version */ 489 case 'V': /* version */
504 print_revision(progname, NP_VERSION); 490 print_revision(progname, NP_VERSION);
@@ -514,48 +500,47 @@ int process_arguments(int argc, char **argv) {
514 } 500 }
515 } 501 }
516 502
517 c = optind; 503 int index = optind;
518
519 set_thresholds(&my_threshold, warning, critical);
520 504
521 while (argc > c) { 505 set_thresholds(&result.config.my_threshold, warning, critical);
522 506
523 if (db_host == NULL) { 507 while (argc > index) {
524 if (is_host(argv[c])) { 508 if (result.config.db_host == NULL) {
525 db_host = argv[c++]; 509 if (is_host(argv[index])) {
510 result.config.db_host = argv[index++];
526 } else { 511 } else {
527 usage2(_("Invalid hostname/address"), argv[c]); 512 usage2(_("Invalid hostname/address"), argv[index]);
528 } 513 }
529 } else if (db_user == NULL) { 514 } else if (result.config.db_user == NULL) {
530 db_user = argv[c++]; 515 result.config.db_user = argv[index++];
531 } else if (db_pass == NULL) { 516 } else if (result.config.db_pass == NULL) {
532 db_pass = argv[c++]; 517 result.config.db_pass = argv[index++];
533 } else if (db == NULL) { 518 } else if (result.config.db == NULL) {
534 db = argv[c++]; 519 result.config.db = argv[index++];
535 } else if (is_intnonneg(argv[c])) { 520 } else if (is_intnonneg(argv[index])) {
536 db_port = atoi(argv[c++]); 521 result.config.db_port = atoi(argv[index++]);
537 } else { 522 } else {
538 break; 523 break;
539 } 524 }
540 } 525 }
541 526
542 return validate_arguments(); 527 return validate_arguments(result);
543} 528}
544 529
545int validate_arguments(void) { 530check_mysql_config_wrapper validate_arguments(check_mysql_config_wrapper config_wrapper) {
546 if (db_user == NULL) { 531 if (config_wrapper.config.db_user == NULL) {
547 db_user = strdup(""); 532 config_wrapper.config.db_user = strdup("");
548 } 533 }
549 534
550 if (db_host == NULL) { 535 if (config_wrapper.config.db_host == NULL) {
551 db_host = strdup(""); 536 config_wrapper.config.db_host = strdup("");
552 } 537 }
553 538
554 if (db == NULL) { 539 if (config_wrapper.config.db == NULL) {
555 db = strdup(""); 540 config_wrapper.config.db = strdup("");
556 } 541 }
557 542
558 return OK; 543 return config_wrapper;
559} 544}
560 545
561void print_help(void) { 546void 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 @@
1#pragma once
2
3#include "../../config.h"
4#include "thresholds.h"
5#include <stddef.h>
6#include <mysql.h>
7
8typedef struct {
9 char *db_host;
10 unsigned int db_port;
11 char *db_user;
12 char *db_socket;
13 char *db_pass;
14 char *db;
15 char *ca_cert;
16 char *ca_dir;
17 char *cert;
18 char *key;
19 char *ciphers;
20 bool ssl;
21 char *opt_file;
22 char *opt_group;
23
24 bool check_replica;
25 bool ignore_auth;
26
27 double warning_time;
28 double critical_time;
29 thresholds *my_threshold;
30
31} check_mysql_config;
32
33check_mysql_config check_mysql_config_init() {
34 check_mysql_config tmp = {
35 .db_host = NULL,
36 .db_port = MYSQL_PORT,
37 .db = NULL,
38 .db_pass = NULL,
39 .db_socket = NULL,
40 .db_user = NULL,
41 .ca_cert = NULL,
42 .ca_dir = NULL,
43 .cert = NULL,
44 .key = NULL,
45 .ciphers = NULL,
46 .ssl = false,
47 .opt_file = NULL,
48 .opt_group = NULL,
49
50 .check_replica = false,
51 .ignore_auth = false,
52
53 .warning_time = 0,
54 .critical_time = 0,
55 .my_threshold = NULL,
56 };
57 return tmp;
58}