diff options
Diffstat (limited to 'plugins/check_mysql_query.c')
| -rw-r--r-- | plugins/check_mysql_query.c | 154 |
1 files changed, 105 insertions, 49 deletions
diff --git a/plugins/check_mysql_query.c b/plugins/check_mysql_query.c index 5e04a94b..ae6cc15d 100644 --- a/plugins/check_mysql_query.c +++ b/plugins/check_mysql_query.c | |||
| @@ -29,11 +29,11 @@ | |||
| 29 | * | 29 | * |
| 30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
| 31 | 31 | ||
| 32 | const char *progname = "check_mysql_query"; | ||
| 33 | const char *copyright = "1999-2024"; | ||
| 34 | const char *email = "devel@monitoring-plugins.org"; | ||
| 35 | |||
| 36 | #include "common.h" | 32 | #include "common.h" |
| 33 | #include "output.h" | ||
| 34 | #include "perfdata.h" | ||
| 35 | #include "states.h" | ||
| 36 | #include "thresholds.h" | ||
| 37 | #include "utils.h" | 37 | #include "utils.h" |
| 38 | #include "utils_base.h" | 38 | #include "utils_base.h" |
| 39 | #include "netutils.h" | 39 | #include "netutils.h" |
| @@ -42,12 +42,17 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 42 | #include <mysql.h> | 42 | #include <mysql.h> |
| 43 | #include <errmsg.h> | 43 | #include <errmsg.h> |
| 44 | 44 | ||
| 45 | const char *progname = "check_mysql_query"; | ||
| 46 | const char *copyright = "1999-2024"; | ||
| 47 | const char *email = "devel@monitoring-plugins.org"; | ||
| 48 | |||
| 45 | typedef struct { | 49 | typedef struct { |
| 46 | int errorcode; | 50 | int errorcode; |
| 47 | check_mysql_query_config config; | 51 | check_mysql_query_config config; |
| 48 | } check_mysql_query_config_wrapper; | 52 | } check_mysql_query_config_wrapper; |
| 49 | static check_mysql_query_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); | 53 | static check_mysql_query_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); |
| 50 | static check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/); | 54 | static check_mysql_query_config_wrapper |
| 55 | validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/); | ||
| 51 | static void print_help(void); | 56 | static void print_help(void); |
| 52 | void print_usage(void); | 57 | void print_usage(void); |
| 53 | 58 | ||
| @@ -68,6 +73,10 @@ int main(int argc, char **argv) { | |||
| 68 | 73 | ||
| 69 | const check_mysql_query_config config = tmp_config.config; | 74 | const check_mysql_query_config config = tmp_config.config; |
| 70 | 75 | ||
| 76 | if (config.output_format_is_set) { | ||
| 77 | mp_set_format(config.output_format); | ||
| 78 | } | ||
| 79 | |||
| 71 | MYSQL mysql; | 80 | MYSQL mysql; |
| 72 | /* initialize mysql */ | 81 | /* initialize mysql */ |
| 73 | mysql_init(&mysql); | 82 | mysql_init(&mysql); |
| @@ -82,26 +91,38 @@ int main(int argc, char **argv) { | |||
| 82 | mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client"); | 91 | mysql_options(&mysql, MYSQL_READ_DEFAULT_GROUP, "client"); |
| 83 | } | 92 | } |
| 84 | 93 | ||
| 94 | mp_check overall = mp_check_init(); | ||
| 95 | mp_subcheck sc_connect = mp_subcheck_init(); | ||
| 96 | |||
| 85 | /* establish a connection to the server and error checking */ | 97 | /* establish a connection to the server and error checking */ |
| 86 | if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, config.db_port, config.db_socket, 0)) { | 98 | if (!mysql_real_connect(&mysql, config.db_host, config.db_user, config.db_pass, config.db, |
| 99 | config.db_port, config.db_socket, 0)) { | ||
| 100 | xasprintf(&sc_connect.output, "query failed: %s", mysql_error(&mysql)); | ||
| 101 | |||
| 87 | if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { | 102 | if (mysql_errno(&mysql) == CR_UNKNOWN_HOST) { |
| 88 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); | 103 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING); |
| 89 | } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { | 104 | } else if (mysql_errno(&mysql) == CR_VERSION_ERROR) { |
| 90 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); | 105 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING); |
| 91 | } else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY) { | 106 | } else if (mysql_errno(&mysql) == CR_OUT_OF_MEMORY) { |
| 92 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); | 107 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING); |
| 93 | } else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR) { | 108 | } else if (mysql_errno(&mysql) == CR_IPSOCK_ERROR) { |
| 94 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); | 109 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING); |
| 95 | } else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR) { | 110 | } else if (mysql_errno(&mysql) == CR_SOCKET_CREATE_ERROR) { |
| 96 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), mysql_error(&mysql)); | 111 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_WARNING); |
| 97 | } else { | 112 | } else { |
| 98 | die(STATE_CRITICAL, "QUERY %s: %s\n", _("CRITICAL"), mysql_error(&mysql)); | 113 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_CRITICAL); |
| 99 | } | 114 | } |
| 115 | |||
| 116 | mp_add_subcheck_to_check(&overall, sc_connect); | ||
| 117 | mp_exit(overall); | ||
| 100 | } | 118 | } |
| 101 | 119 | ||
| 102 | char *error = NULL; | 120 | sc_connect = mp_set_subcheck_state(sc_connect, STATE_OK); |
| 121 | xasprintf(&sc_connect.output, "query succeeded"); | ||
| 122 | mp_add_subcheck_to_check(&overall, sc_connect); | ||
| 123 | |||
| 103 | if (mysql_query(&mysql, config.sql_query) != 0) { | 124 | if (mysql_query(&mysql, config.sql_query) != 0) { |
| 104 | error = strdup(mysql_error(&mysql)); | 125 | char *error = strdup(mysql_error(&mysql)); |
| 105 | mysql_close(&mysql); | 126 | mysql_close(&mysql); |
| 106 | die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error); | 127 | die(STATE_CRITICAL, "QUERY %s: %s - %s\n", _("CRITICAL"), _("Error with query"), error); |
| 107 | } | 128 | } |
| @@ -109,7 +130,7 @@ int main(int argc, char **argv) { | |||
| 109 | MYSQL_RES *res; | 130 | MYSQL_RES *res; |
| 110 | /* store the result */ | 131 | /* store the result */ |
| 111 | if ((res = mysql_store_result(&mysql)) == NULL) { | 132 | if ((res = mysql_store_result(&mysql)) == NULL) { |
| 112 | error = strdup(mysql_error(&mysql)); | 133 | char *error = strdup(mysql_error(&mysql)); |
| 113 | mysql_close(&mysql); | 134 | mysql_close(&mysql); |
| 114 | die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error); | 135 | die(STATE_CRITICAL, "QUERY %s: Error with store_result - %s\n", _("CRITICAL"), error); |
| 115 | } | 136 | } |
| @@ -120,17 +141,24 @@ int main(int argc, char **argv) { | |||
| 120 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned")); | 141 | die(STATE_WARNING, "QUERY %s: %s\n", _("WARNING"), _("No rows returned")); |
| 121 | } | 142 | } |
| 122 | 143 | ||
| 144 | mp_subcheck sc_value = mp_subcheck_init(); | ||
| 123 | MYSQL_ROW row; | 145 | MYSQL_ROW row; |
| 124 | /* fetch the first row */ | 146 | /* fetch the first row */ |
| 125 | if ((row = mysql_fetch_row(res)) == NULL) { | 147 | if ((row = mysql_fetch_row(res)) == NULL) { |
| 126 | error = strdup(mysql_error(&mysql)); | 148 | xasprintf(&sc_value.output, "fetch row error - %s", mysql_error(&mysql)); |
| 127 | mysql_free_result(res); | 149 | mysql_free_result(res); |
| 128 | mysql_close(&mysql); | 150 | mysql_close(&mysql); |
| 129 | die(STATE_CRITICAL, "QUERY %s: Fetch row error - %s\n", _("CRITICAL"), error); | 151 | |
| 152 | sc_value = mp_set_subcheck_state(sc_value, STATE_CRITICAL); | ||
| 153 | mp_add_subcheck_to_check(&overall, sc_value); | ||
| 154 | mp_exit(overall); | ||
| 130 | } | 155 | } |
| 131 | 156 | ||
| 132 | if (!is_numeric(row[0])) { | 157 | if (!is_numeric(row[0])) { |
| 133 | die(STATE_CRITICAL, "QUERY %s: %s - '%s'\n", _("CRITICAL"), _("Is not a numeric"), row[0]); | 158 | xasprintf(&sc_value.output, "query result is not numeric"); |
| 159 | sc_value = mp_set_subcheck_state(sc_value, STATE_CRITICAL); | ||
| 160 | mp_add_subcheck_to_check(&overall, sc_value); | ||
| 161 | mp_exit(overall); | ||
| 134 | } | 162 | } |
| 135 | 163 | ||
| 136 | double value = strtod(row[0], NULL); | 164 | double value = strtod(row[0], NULL); |
| @@ -145,31 +173,42 @@ int main(int argc, char **argv) { | |||
| 145 | printf("mysql result: %f\n", value); | 173 | printf("mysql result: %f\n", value); |
| 146 | } | 174 | } |
| 147 | 175 | ||
| 148 | int status = get_status(value, config.my_thresholds); | 176 | mp_perfdata pd_query_result = perfdata_init(); |
| 177 | pd_query_result = mp_set_pd_value(pd_query_result, value); | ||
| 178 | pd_query_result = mp_pd_set_thresholds(pd_query_result, config.thresholds); | ||
| 179 | pd_query_result.label = "result"; | ||
| 180 | mp_add_perfdata_to_subcheck(&sc_value, pd_query_result); | ||
| 149 | 181 | ||
| 150 | if (status == STATE_OK) { | 182 | sc_value = mp_set_subcheck_state(sc_value, mp_get_pd_status(pd_query_result)); |
| 151 | printf("QUERY %s: ", _("OK")); | 183 | xasprintf(&sc_value.output, "'%s' returned '%f'", config.sql_query, value); |
| 152 | } else if (status == STATE_WARNING) { | 184 | |
| 153 | printf("QUERY %s: ", _("WARNING")); | 185 | mp_add_subcheck_to_check(&overall, sc_value); |
| 154 | } else if (status == STATE_CRITICAL) { | ||
| 155 | printf("QUERY %s: ", _("CRITICAL")); | ||
| 156 | } | ||
| 157 | printf(_("'%s' returned %f | %s"), config.sql_query, value, | ||
| 158 | fperfdata("result", value, "", config.my_thresholds->warning, config.my_thresholds->warning ? config.my_thresholds->warning->end : 0, | ||
| 159 | config.my_thresholds->critical, config.my_thresholds->critical ? config.my_thresholds->critical->end : 0, false, 0, false, 0)); | ||
| 160 | printf("\n"); | ||
| 161 | 186 | ||
| 162 | return status; | 187 | mp_exit(overall); |
| 163 | } | 188 | } |
| 164 | 189 | ||
| 165 | /* process command-line arguments */ | 190 | /* process command-line arguments */ |
| 166 | check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { | 191 | check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { |
| 167 | static struct option longopts[] = { | 192 | enum { |
| 168 | {"hostname", required_argument, 0, 'H'}, {"socket", required_argument, 0, 's'}, {"database", required_argument, 0, 'd'}, | 193 | output_format_index = CHAR_MAX + 1, |
| 169 | {"username", required_argument, 0, 'u'}, {"password", required_argument, 0, 'p'}, {"file", required_argument, 0, 'f'}, | 194 | }; |
| 170 | {"group", required_argument, 0, 'g'}, {"port", required_argument, 0, 'P'}, {"verbose", no_argument, 0, 'v'}, | 195 | |
| 171 | {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {"query", required_argument, 0, 'q'}, | 196 | static struct option longopts[] = {{"hostname", required_argument, 0, 'H'}, |
| 172 | {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, {0, 0, 0, 0}}; | 197 | {"socket", required_argument, 0, 's'}, |
| 198 | {"database", required_argument, 0, 'd'}, | ||
| 199 | {"username", required_argument, 0, 'u'}, | ||
| 200 | {"password", required_argument, 0, 'p'}, | ||
| 201 | {"file", required_argument, 0, 'f'}, | ||
| 202 | {"group", required_argument, 0, 'g'}, | ||
| 203 | {"port", required_argument, 0, 'P'}, | ||
| 204 | {"verbose", no_argument, 0, 'v'}, | ||
| 205 | {"version", no_argument, 0, 'V'}, | ||
| 206 | {"help", no_argument, 0, 'h'}, | ||
| 207 | {"query", required_argument, 0, 'q'}, | ||
| 208 | {"warning", required_argument, 0, 'w'}, | ||
| 209 | {"critical", required_argument, 0, 'c'}, | ||
| 210 | {"output-format", required_argument, 0, output_format_index}, | ||
| 211 | {0, 0, 0, 0}}; | ||
| 173 | 212 | ||
| 174 | check_mysql_query_config_wrapper result = { | 213 | check_mysql_query_config_wrapper result = { |
| 175 | .errorcode = OK, | 214 | .errorcode = OK, |
| @@ -181,9 +220,6 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { | |||
| 181 | return result; | 220 | return result; |
| 182 | } | 221 | } |
| 183 | 222 | ||
| 184 | char *warning = NULL; | ||
| 185 | char *critical = NULL; | ||
| 186 | |||
| 187 | while (true) { | 223 | while (true) { |
| 188 | int option = 0; | 224 | int option = 0; |
| 189 | int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option); | 225 | int option_char = getopt_long(argc, argv, "hvVP:p:u:d:H:s:q:w:c:f:g:", longopts, &option); |
| @@ -239,23 +275,41 @@ check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { | |||
| 239 | case 'q': | 275 | case 'q': |
| 240 | xasprintf(&result.config.sql_query, "%s", optarg); | 276 | xasprintf(&result.config.sql_query, "%s", optarg); |
| 241 | break; | 277 | break; |
| 242 | case 'w': | 278 | case 'w': { |
| 243 | warning = optarg; | 279 | mp_range_parsed tmp = mp_parse_range_string(optarg); |
| 244 | break; | 280 | if (tmp.error != MP_PARSING_SUCCES) { |
| 245 | case 'c': | 281 | die(STATE_UNKNOWN, "failed to parse warning threshold"); |
| 246 | critical = optarg; | 282 | } |
| 247 | break; | 283 | result.config.thresholds = mp_thresholds_set_warn(result.config.thresholds, tmp.range); |
| 284 | } break; | ||
| 285 | case 'c': { | ||
| 286 | mp_range_parsed tmp = mp_parse_range_string(optarg); | ||
| 287 | if (tmp.error != MP_PARSING_SUCCES) { | ||
| 288 | die(STATE_UNKNOWN, "failed to parse critical threshold"); | ||
| 289 | } | ||
| 290 | result.config.thresholds = mp_thresholds_set_crit(result.config.thresholds, tmp.range); | ||
| 291 | } break; | ||
| 248 | case '?': /* help */ | 292 | case '?': /* help */ |
| 249 | usage5(); | 293 | usage5(); |
| 294 | case output_format_index: { | ||
| 295 | parsed_output_format parser = mp_parse_output_format(optarg); | ||
| 296 | if (!parser.parsing_success) { | ||
| 297 | printf("Invalid output format: %s\n", optarg); | ||
| 298 | exit(STATE_UNKNOWN); | ||
| 299 | } | ||
| 300 | |||
| 301 | result.config.output_format_is_set = true; | ||
| 302 | result.config.output_format = parser.output_format; | ||
| 303 | break; | ||
| 304 | } | ||
| 250 | } | 305 | } |
| 251 | } | 306 | } |
| 252 | 307 | ||
| 253 | set_thresholds(&result.config.my_thresholds, warning, critical); | ||
| 254 | |||
| 255 | return validate_arguments(result); | 308 | return validate_arguments(result); |
| 256 | } | 309 | } |
| 257 | 310 | ||
| 258 | check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper config_wrapper) { | 311 | check_mysql_query_config_wrapper |
| 312 | validate_arguments(check_mysql_query_config_wrapper config_wrapper) { | ||
| 259 | if (config_wrapper.config.sql_query == NULL) { | 313 | if (config_wrapper.config.sql_query == NULL) { |
| 260 | usage("Must specify a SQL query to run"); | 314 | usage("Must specify a SQL query to run"); |
| 261 | } | 315 | } |
| @@ -310,6 +364,8 @@ void print_help(void) { | |||
| 310 | printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); | 364 | printf(" ==> %s <==\n", _("IMPORTANT: THIS FORM OF AUTHENTICATION IS NOT SECURE!!!")); |
| 311 | printf(" %s\n", _("Your clear-text password could be visible as a process table entry")); | 365 | printf(" %s\n", _("Your clear-text password could be visible as a process table entry")); |
| 312 | 366 | ||
| 367 | printf(UT_OUTPUT_FORMAT); | ||
| 368 | |||
| 313 | printf("\n"); | 369 | printf("\n"); |
| 314 | printf(" %s\n", _("A query is required. The result from the query should be numeric.")); | 370 | printf(" %s\n", _("A query is required. The result from the query should be numeric.")); |
| 315 | printf(" %s\n", _("For extra security, create a user with minimal access.")); | 371 | printf(" %s\n", _("For extra security, create a user with minimal access.")); |
