summaryrefslogtreecommitdiffstats
path: root/plugins/check_mysql_query.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_mysql_query.c')
-rw-r--r--plugins/check_mysql_query.c154
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
32const char *progname = "check_mysql_query";
33const char *copyright = "1999-2024";
34const 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
45const char *progname = "check_mysql_query";
46const char *copyright = "1999-2024";
47const char *email = "devel@monitoring-plugins.org";
48
45typedef struct { 49typedef 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;
49static check_mysql_query_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/); 53static check_mysql_query_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
50static check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/); 54static check_mysql_query_config_wrapper
55 validate_arguments(check_mysql_query_config_wrapper /*config_wrapper*/);
51static void print_help(void); 56static void print_help(void);
52void print_usage(void); 57void 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 */
166check_mysql_query_config_wrapper process_arguments(int argc, char **argv) { 191check_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
258check_mysql_query_config_wrapper validate_arguments(check_mysql_query_config_wrapper config_wrapper) { 311check_mysql_query_config_wrapper
312validate_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."));