diff options
Diffstat (limited to 'plugins/check_mysql.c')
-rw-r--r-- | plugins/check_mysql.c | 132 |
1 files changed, 85 insertions, 47 deletions
diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c index ca3422b5..6134d6c6 100644 --- a/plugins/check_mysql.c +++ b/plugins/check_mysql.c | |||
@@ -50,15 +50,23 @@ static int verbose = 0; | |||
50 | 50 | ||
51 | #define LENGTH_METRIC_UNIT 6 | 51 | #define LENGTH_METRIC_UNIT 6 |
52 | static const char *metric_unit[LENGTH_METRIC_UNIT] = { | 52 | static const char *metric_unit[LENGTH_METRIC_UNIT] = { |
53 | "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", |
54 | "Threads_connected", "Threads_running"}; | ||
54 | 55 | ||
55 | #define LENGTH_METRIC_COUNTER 9 | 56 | #define LENGTH_METRIC_COUNTER 9 |
56 | static const char *metric_counter[LENGTH_METRIC_COUNTER] = { | 57 | static const char *metric_counter[LENGTH_METRIC_COUNTER] = {"Connections", |
57 | "Connections", "Qcache_hits", "Qcache_inserts", "Qcache_lowmem_prunes", "Qcache_not_cached", "Queries", | 58 | "Qcache_hits", |
58 | "Questions", "Table_locks_waited", "Uptime"}; | 59 | "Qcache_inserts", |
59 | 60 | "Qcache_lowmem_prunes", | |
60 | #define MYSQLDUMP_THREADS_QUERY \ | 61 | "Qcache_not_cached", |
61 | "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE 'SELECT /*!40001 SQL_NO_CACHE */%'" | 62 | "Queries", |
63 | "Questions", | ||
64 | "Table_locks_waited", | ||
65 | "Uptime"}; | ||
66 | |||
67 | #define MYSQLDUMP_THREADS_QUERY \ | ||
68 | "SELECT COUNT(1) mysqldumpThreads FROM information_schema.processlist WHERE info LIKE " \ | ||
69 | "'SELECT /*!40001 SQL_NO_CACHE */%'" | ||
62 | 70 | ||
63 | typedef struct { | 71 | typedef struct { |
64 | int errorcode; | 72 | int errorcode; |
@@ -99,16 +107,19 @@ int main(int argc, char **argv) { | |||
99 | } | 107 | } |
100 | 108 | ||
101 | if (config.ssl) { | 109 | if (config.ssl) { |
102 | mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, config.ciphers); | 110 | mysql_ssl_set(&mysql, config.key, config.cert, config.ca_cert, config.ca_dir, |
111 | config.ciphers); | ||
103 | } | 112 | } |
104 | /* establish a connection to the server and error checking */ | 113 | /* establish a connection to the server and error checking */ |
105 | if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) { | 114 | if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, |
115 | config.db_port, config.db_socket, 0)) { | ||
106 | /* Depending on internally-selected auth plugin MySQL might return */ | 116 | /* Depending on internally-selected auth plugin MySQL might return */ |
107 | /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */ | 117 | /* ER_ACCESS_DENIED_NO_PASSWORD_ERROR or ER_ACCESS_DENIED_ERROR. */ |
108 | /* Semantically these errors are the same. */ | 118 | /* Semantically these errors are the same. */ |
109 | if (config.ignore_auth && | 119 | if (config.ignore_auth && (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || |
110 | (mysql_errno(&mysql) == ER_ACCESS_DENIED_ERROR || mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { | 120 | mysql_errno(&mysql) == ER_ACCESS_DENIED_NO_PASSWORD_ERROR)) { |
111 | printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), mysql_get_proto_info(&mysql)); | 121 | printf("MySQL OK - Version: %s (protocol %d)\n", mysql_get_server_info(&mysql), |
122 | mysql_get_proto_info(&mysql)); | ||
112 | mysql_close(&mysql); | 123 | mysql_close(&mysql); |
113 | return STATE_OK; | 124 | return STATE_OK; |
114 | } | 125 | } |
@@ -157,13 +168,17 @@ int main(int argc, char **argv) { | |||
157 | while ((row = mysql_fetch_row(res)) != NULL) { | 168 | while ((row = mysql_fetch_row(res)) != NULL) { |
158 | for (int i = 0; i < LENGTH_METRIC_UNIT; i++) { | 169 | for (int i = 0; i < LENGTH_METRIC_UNIT; i++) { |
159 | if (strcmp(row[0], metric_unit[i]) == 0) { | 170 | if (strcmp(row[0], metric_unit[i]) == 0) { |
160 | xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, 0, false, 0)); | 171 | xasprintf(&perf, "%s%s ", perf, |
172 | perfdata(metric_unit[i], atol(row[1]), "", false, 0, false, 0, false, | ||
173 | 0, false, 0)); | ||
161 | continue; | 174 | continue; |
162 | } | 175 | } |
163 | } | 176 | } |
164 | for (int i = 0; i < LENGTH_METRIC_COUNTER; i++) { | 177 | for (int i = 0; i < LENGTH_METRIC_COUNTER; i++) { |
165 | if (strcmp(row[0], metric_counter[i]) == 0) { | 178 | if (strcmp(row[0], metric_counter[i]) == 0) { |
166 | xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, false, 0, false, 0)); | 179 | xasprintf(&perf, "%s%s ", perf, |
180 | perfdata(metric_counter[i], atol(row[1]), "c", false, 0, false, 0, | ||
181 | false, 0, false, 0)); | ||
167 | continue; | 182 | continue; |
168 | } | 183 | } |
169 | } | 184 | } |
@@ -189,8 +204,8 @@ int main(int argc, char **argv) { | |||
189 | unsigned long minor_version = (server_verion_int % 10000) / 100; | 204 | unsigned long minor_version = (server_verion_int % 10000) / 100; |
190 | unsigned long patch_version = (server_verion_int % 100); | 205 | unsigned long patch_version = (server_verion_int % 100); |
191 | if (verbose) { | 206 | if (verbose) { |
192 | printf("Found MariaDB: %s, main version: %lu, minor version: %lu, patch version: %lu\n", server_version, major_version, | 207 | printf("Found MariaDB: %s, main version: %lu, minor version: %lu, patch version: %lu\n", |
193 | minor_version, patch_version); | 208 | server_version, major_version, minor_version, patch_version); |
194 | } | 209 | } |
195 | 210 | ||
196 | if (strstr(server_version, "MariaDB") != NULL) { | 211 | if (strstr(server_version, "MariaDB") != NULL) { |
@@ -204,16 +219,13 @@ int main(int argc, char **argv) { | |||
204 | use_deprecated_slave_status = true; | 219 | use_deprecated_slave_status = true; |
205 | } | 220 | } |
206 | } | 221 | } |
207 | } else if (strstr(server_version, "MySQL") != NULL) { | 222 | } else { |
208 | // Looks like MySQL | 223 | // Looks like MySQL or at least not like MariaDB |
209 | if (major_version < 8) { | 224 | if (major_version < 8) { |
210 | use_deprecated_slave_status = true; | 225 | use_deprecated_slave_status = true; |
211 | } else if (major_version == 10 && minor_version < 4) { | 226 | } else if (major_version == 10 && minor_version < 4) { |
212 | use_deprecated_slave_status = true; | 227 | use_deprecated_slave_status = true; |
213 | } | 228 | } |
214 | } else { | ||
215 | printf("Not a known sever implementation: %s\n", server_version); | ||
216 | exit(STATE_UNKNOWN); | ||
217 | } | 229 | } |
218 | 230 | ||
219 | char *replica_query = NULL; | 231 | char *replica_query = NULL; |
@@ -270,17 +282,32 @@ int main(int argc, char **argv) { | |||
270 | num_fields = mysql_num_fields(res); | 282 | num_fields = mysql_num_fields(res); |
271 | fields = mysql_fetch_fields(res); | 283 | fields = mysql_fetch_fields(res); |
272 | for (int i = 0; i < num_fields; i++) { | 284 | for (int i = 0; i < num_fields; i++) { |
273 | if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { | 285 | if (use_deprecated_slave_status) { |
274 | replica_io_field = i; | 286 | if (strcmp(fields[i].name, "Slave_IO_Running") == 0) { |
275 | continue; | 287 | replica_io_field = i; |
276 | } | 288 | continue; |
277 | if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) { | 289 | } |
278 | replica_sql_field = i; | 290 | if (strcmp(fields[i].name, "Slave_SQL_Running") == 0) { |
279 | continue; | 291 | replica_sql_field = i; |
280 | } | 292 | continue; |
281 | if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) { | 293 | } |
282 | seconds_behind_field = i; | 294 | if (strcmp(fields[i].name, "Seconds_Behind_Master") == 0) { |
283 | continue; | 295 | seconds_behind_field = i; |
296 | continue; | ||
297 | } | ||
298 | } else { | ||
299 | if (strcmp(fields[i].name, "Replica_IO_Running") == 0) { | ||
300 | replica_io_field = i; | ||
301 | continue; | ||
302 | } | ||
303 | if (strcmp(fields[i].name, "Replica_SQL_Running") == 0) { | ||
304 | replica_sql_field = i; | ||
305 | continue; | ||
306 | } | ||
307 | if (strcmp(fields[i].name, "Seconds_Behind_Source") == 0) { | ||
308 | seconds_behind_field = i; | ||
309 | continue; | ||
310 | } | ||
284 | } | 311 | } |
285 | } | 312 | } |
286 | 313 | ||
@@ -292,11 +319,15 @@ int main(int argc, char **argv) { | |||
292 | } | 319 | } |
293 | 320 | ||
294 | /* Save replica status in replica_result */ | 321 | /* Save replica status in replica_result */ |
295 | snprintf(replica_result, REPLICA_RESULTSIZE, "Replica IO: %s Replica SQL: %s Seconds Behind Master: %s", row[replica_io_field], | 322 | snprintf(replica_result, REPLICA_RESULTSIZE, |
296 | row[replica_sql_field], seconds_behind_field != -1 ? row[seconds_behind_field] : "Unknown"); | 323 | "Replica IO: %s Replica SQL: %s Seconds Behind Master: %s", |
297 | 324 | row[replica_io_field], row[replica_sql_field], | |
298 | /* Raise critical error if SQL THREAD or IO THREAD are stopped, but only if there are no mysqldump threads running */ | 325 | seconds_behind_field != -1 ? row[seconds_behind_field] : "Unknown"); |
299 | if (strcmp(row[replica_io_field], "Yes") != 0 || strcmp(row[replica_sql_field], "Yes") != 0) { | 326 | |
327 | /* Raise critical error if SQL THREAD or IO THREAD are stopped, but only if there are no | ||
328 | * mysqldump threads running */ | ||
329 | if (strcmp(row[replica_io_field], "Yes") != 0 || | ||
330 | strcmp(row[replica_sql_field], "Yes") != 0) { | ||
300 | MYSQL_RES *res_mysqldump; | 331 | MYSQL_RES *res_mysqldump; |
301 | MYSQL_ROW row_mysqldump; | 332 | MYSQL_ROW row_mysqldump; |
302 | unsigned int mysqldump_threads = 0; | 333 | unsigned int mysqldump_threads = 0; |
@@ -325,20 +356,23 @@ int main(int argc, char **argv) { | |||
325 | if (seconds_behind_field == -1) { | 356 | if (seconds_behind_field == -1) { |
326 | printf("seconds_behind_field not found\n"); | 357 | printf("seconds_behind_field not found\n"); |
327 | } else { | 358 | } else { |
328 | printf("seconds_behind_field(index %d)=%s\n", seconds_behind_field, row[seconds_behind_field]); | 359 | printf("seconds_behind_field(index %d)=%s\n", seconds_behind_field, |
360 | row[seconds_behind_field]); | ||
329 | } | 361 | } |
330 | } | 362 | } |
331 | 363 | ||
332 | /* Check Seconds Behind against threshold */ | 364 | /* Check Seconds Behind against threshold */ |
333 | if ((seconds_behind_field != -1) && (row[seconds_behind_field] != NULL && strcmp(row[seconds_behind_field], "NULL") != 0)) { | 365 | if ((seconds_behind_field != -1) && (row[seconds_behind_field] != NULL && |
366 | strcmp(row[seconds_behind_field], "NULL") != 0)) { | ||
334 | double value = atof(row[seconds_behind_field]); | 367 | double value = atof(row[seconds_behind_field]); |
335 | int status; | 368 | int status; |
336 | 369 | ||
337 | status = get_status(value, config.my_threshold); | 370 | status = get_status(value, config.my_threshold); |
338 | 371 | ||
339 | xasprintf(&perf, "%s %s", perf, | 372 | xasprintf(&perf, "%s %s", perf, |
340 | fperfdata("seconds behind master", value, "s", true, (double)config.warning_time, true, | 373 | fperfdata("seconds behind master", value, "s", true, |
341 | (double)config.critical_time, false, 0, false, 0)); | 374 | (double)config.warning_time, true, (double)config.critical_time, |
375 | false, 0, false, 0)); | ||
342 | 376 | ||
343 | if (status == STATE_WARNING) { | 377 | if (status == STATE_WARNING) { |
344 | printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf); | 378 | printf("SLOW_REPLICA %s: %s|%s\n", _("WARNING"), replica_result, perf); |
@@ -410,7 +444,8 @@ check_mysql_config_wrapper process_arguments(int argc, char **argv) { | |||
410 | 444 | ||
411 | int option = 0; | 445 | int option = 0; |
412 | while (true) { | 446 | 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); | 447 | int option_index = |
448 | getopt_long(argc, argv, "hlvVnSP:p:u:d:H:s:c:w:a:k:C:D:L:f:g:", longopts, &option); | ||
414 | 449 | ||
415 | if (option_index == -1 || option_index == EOF) { | 450 | if (option_index == -1 || option_index == EOF) { |
416 | break; | 451 | break; |
@@ -580,15 +615,17 @@ void print_help(void) { | |||
580 | printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); | 615 | printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); |
581 | printf(" %s\n", _("Your clear-text password could be visible as a process table entry")); | 616 | printf(" %s\n", _("Your clear-text password could be visible as a process table entry")); |
582 | printf(" %s\n", "-S, --check-slave"); | 617 | printf(" %s\n", "-S, --check-slave"); |
583 | printf(" %s\n", | 618 | printf(" %s\n", _("Check if the slave thread is running properly. This option is deprecated " |
584 | _("Check if the slave thread is running properly. This option is deprecated in favour of check-replica, which does the same")); | 619 | "in favour of check-replica, which does the same")); |
585 | printf(" %s\n", "--check-replica"); | 620 | printf(" %s\n", "--check-replica"); |
586 | printf(" %s\n", _("Check if the replica thread is running properly.")); | 621 | printf(" %s\n", _("Check if the replica thread is running properly.")); |
587 | printf(" %s\n", "-w, --warning"); | 622 | printf(" %s\n", "-w, --warning"); |
588 | printf(" %s\n", _("Exit with WARNING status if replica server is more than INTEGER seconds")); | 623 | printf(" %s\n", |
624 | _("Exit with WARNING status if replica server is more than INTEGER seconds")); | ||
589 | printf(" %s\n", _("behind master")); | 625 | printf(" %s\n", _("behind master")); |
590 | printf(" %s\n", "-c, --critical"); | 626 | printf(" %s\n", "-c, --critical"); |
591 | printf(" %s\n", _("Exit with CRITICAL status if replica server is more then INTEGER seconds")); | 627 | printf(" %s\n", |
628 | _("Exit with CRITICAL status if replica server is more then INTEGER seconds")); | ||
592 | printf(" %s\n", _("behind master")); | 629 | printf(" %s\n", _("behind master")); |
593 | printf(" %s\n", "-l, --ssl"); | 630 | printf(" %s\n", "-l, --ssl"); |
594 | printf(" %s\n", _("Use ssl encryption")); | 631 | printf(" %s\n", _("Use ssl encryption")); |
@@ -604,7 +641,8 @@ void print_help(void) { | |||
604 | printf(" %s\n", _("List of valid SSL ciphers")); | 641 | printf(" %s\n", _("List of valid SSL ciphers")); |
605 | 642 | ||
606 | printf("\n"); | 643 | printf("\n"); |
607 | printf(" %s\n", _("There are no required arguments. By default, the local database is checked")); | 644 | printf(" %s\n", |
645 | _("There are no required arguments. By default, the local database is checked")); | ||
608 | printf(" %s\n", _("using the default unix socket. You can force TCP on localhost by using an")); | 646 | printf(" %s\n", _("using the default unix socket. You can force TCP on localhost by using an")); |
609 | printf(" %s\n", _("IP address or FQDN ('localhost' will use the socket as well).")); | 647 | printf(" %s\n", _("IP address or FQDN ('localhost' will use the socket as well).")); |
610 | 648 | ||