diff options
| author | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2024-10-31 15:27:01 +0100 |
|---|---|---|
| committer | Lorenz Kästle <12514511+RincewindsHat@users.noreply.github.com> | 2024-10-31 15:27:01 +0100 |
| commit | fa15fdcf5dc2d40aba2f8520108e552b73b1df2b (patch) | |
| tree | d51d62db024b317091f42d9ee540da7371e9d170 /plugins/check_dbi.c | |
| parent | 0fd0421052fed1972ecbdfdabecba5a616eaa109 (diff) | |
| parent | 87eb2bef1ee2a6a42793437b2f5d63f41b1e1806 (diff) | |
| download | monitoring-plugins-fa15fdcf5dc2d40aba2f8520108e552b73b1df2b.tar.gz | |
Merge branch 'master' into fix/check_ssh-variable-stuff
Diffstat (limited to 'plugins/check_dbi.c')
| -rw-r--r-- | plugins/check_dbi.c | 827 |
1 files changed, 387 insertions, 440 deletions
diff --git a/plugins/check_dbi.c b/plugins/check_dbi.c index 29c85206..96575672 100644 --- a/plugins/check_dbi.c +++ b/plugins/check_dbi.c | |||
| @@ -1,36 +1,36 @@ | |||
| 1 | /***************************************************************************** | 1 | /***************************************************************************** |
| 2 | * | 2 | * |
| 3 | * Monitoring check_dbi plugin | 3 | * Monitoring check_dbi plugin |
| 4 | * | 4 | * |
| 5 | * License: GPL | 5 | * License: GPL |
| 6 | * Copyright (c) 2011 Monitoring Plugins Development Team | 6 | * Copyright (c) 2011-2024 Monitoring Plugins Development Team |
| 7 | * Author: Sebastian 'tokkee' Harl <sh@teamix.net> | 7 | * Original Author: Sebastian 'tokkee' Harl <sh@teamix.net> |
| 8 | * | 8 | * |
| 9 | * Description: | 9 | * Description: |
| 10 | * | 10 | * |
| 11 | * This file contains the check_dbi plugin | 11 | * This file contains the check_dbi plugin |
| 12 | * | 12 | * |
| 13 | * Runs an arbitrary (SQL) command and checks the result. | 13 | * Runs an arbitrary (SQL) command and checks the result. |
| 14 | * | 14 | * |
| 15 | * | 15 | * |
| 16 | * This program is free software: you can redistribute it and/or modify | 16 | * This program is free software: you can redistribute it and/or modify |
| 17 | * it under the terms of the GNU General Public License as published by | 17 | * it under the terms of the GNU General Public License as published by |
| 18 | * the Free Software Foundation, either version 3 of the License, or | 18 | * the Free Software Foundation, either version 3 of the License, or |
| 19 | * (at your option) any later version. | 19 | * (at your option) any later version. |
| 20 | * | 20 | * |
| 21 | * This program is distributed in the hope that it will be useful, | 21 | * This program is distributed in the hope that it will be useful, |
| 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 24 | * GNU General Public License for more details. | 24 | * GNU General Public License for more details. |
| 25 | * | 25 | * |
| 26 | * You should have received a copy of the GNU General Public License | 26 | * You should have received a copy of the GNU General Public License |
| 27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 27 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 28 | * | 28 | * |
| 29 | * | 29 | * |
| 30 | *****************************************************************************/ | 30 | *****************************************************************************/ |
| 31 | 31 | ||
| 32 | const char *progname = "check_dbi"; | 32 | const char *progname = "check_dbi"; |
| 33 | const char *copyright = "2011"; | 33 | const char *copyright = "2011-2024"; |
| 34 | const char *email = "devel@monitoring-plugins.org"; | 34 | const char *email = "devel@monitoring-plugins.org"; |
| 35 | 35 | ||
| 36 | #include "common.h" | 36 | #include "common.h" |
| @@ -43,7 +43,7 @@ const char *email = "devel@monitoring-plugins.org"; | |||
| 43 | 43 | ||
| 44 | /* required for NAN */ | 44 | /* required for NAN */ |
| 45 | #ifndef _ISOC99_SOURCE | 45 | #ifndef _ISOC99_SOURCE |
| 46 | #define _ISOC99_SOURCE | 46 | # define _ISOC99_SOURCE |
| 47 | #endif | 47 | #endif |
| 48 | 48 | ||
| 49 | #include <assert.h> | 49 | #include <assert.h> |
| @@ -70,42 +70,40 @@ typedef struct { | |||
| 70 | char *value; | 70 | char *value; |
| 71 | } driver_option_t; | 71 | } driver_option_t; |
| 72 | 72 | ||
| 73 | char *host = NULL; | 73 | static char *host = NULL; |
| 74 | int verbose = 0; | 74 | static int verbose = 0; |
| 75 | 75 | ||
| 76 | char *warning_range = NULL; | 76 | static char *warning_range = NULL; |
| 77 | char *critical_range = NULL; | 77 | static char *critical_range = NULL; |
| 78 | thresholds *dbi_thresholds = NULL; | 78 | static thresholds *dbi_thresholds = NULL; |
| 79 | 79 | ||
| 80 | char *expect = NULL; | 80 | static char *expect = NULL; |
| 81 | 81 | ||
| 82 | regex_t expect_re; | 82 | static regex_t expect_re; |
| 83 | char *expect_re_str = NULL; | 83 | static char *expect_re_str = NULL; |
| 84 | int expect_re_cflags = 0; | 84 | static int expect_re_cflags = 0; |
| 85 | 85 | ||
| 86 | np_dbi_metric_t metric = METRIC_QUERY_RESULT; | 86 | static np_dbi_metric_t metric = METRIC_QUERY_RESULT; |
| 87 | np_dbi_type_t type = TYPE_NUMERIC; | 87 | static np_dbi_type_t type = TYPE_NUMERIC; |
| 88 | 88 | ||
| 89 | char *np_dbi_driver = NULL; | 89 | static char *np_dbi_driver = NULL; |
| 90 | driver_option_t *np_dbi_options = NULL; | 90 | static driver_option_t *np_dbi_options = NULL; |
| 91 | int np_dbi_options_num = 0; | 91 | static int np_dbi_options_num = 0; |
| 92 | char *np_dbi_database = NULL; | 92 | static char *np_dbi_database = NULL; |
| 93 | char *np_dbi_query = NULL; | 93 | static char *np_dbi_query = NULL; |
| 94 | 94 | ||
| 95 | int process_arguments (int, char **); | 95 | static int process_arguments(int, char **); |
| 96 | int validate_arguments (void); | 96 | static int validate_arguments(void); |
| 97 | void print_usage (void); | 97 | void print_usage(void); |
| 98 | void print_help (void); | 98 | static void print_help(void); |
| 99 | 99 | ||
| 100 | double timediff (struct timeval, struct timeval); | 100 | static double timediff(struct timeval, struct timeval); |
| 101 | 101 | ||
| 102 | void np_dbi_print_error (dbi_conn, char *, ...); | 102 | static void np_dbi_print_error(dbi_conn, char *, ...); |
| 103 | 103 | ||
| 104 | int do_query (dbi_conn, const char **, double *, double *); | 104 | static int do_query(dbi_conn, const char **, double *, double *); |
| 105 | 105 | ||
| 106 | int | 106 | int main(int argc, char **argv) { |
| 107 | main (int argc, char **argv) | ||
| 108 | { | ||
| 109 | int status = STATE_UNKNOWN; | 107 | int status = STATE_UNKNOWN; |
| 110 | 108 | ||
| 111 | dbi_driver driver; | 109 | dbi_driver driver; |
| @@ -113,7 +111,8 @@ main (int argc, char **argv) | |||
| 113 | 111 | ||
| 114 | unsigned int server_version; | 112 | unsigned int server_version; |
| 115 | 113 | ||
| 116 | struct timeval start_timeval, end_timeval; | 114 | struct timeval start_timeval; |
| 115 | struct timeval end_timeval; | ||
| 117 | double conn_time = 0.0; | 116 | double conn_time = 0.0; |
| 118 | double query_time = 0.0; | 117 | double query_time = 0.0; |
| 119 | 118 | ||
| @@ -122,59 +121,58 @@ main (int argc, char **argv) | |||
| 122 | 121 | ||
| 123 | int i; | 122 | int i; |
| 124 | 123 | ||
| 125 | setlocale (LC_ALL, ""); | 124 | setlocale(LC_ALL, ""); |
| 126 | bindtextdomain (PACKAGE, LOCALEDIR); | 125 | bindtextdomain(PACKAGE, LOCALEDIR); |
| 127 | textdomain (PACKAGE); | 126 | textdomain(PACKAGE); |
| 128 | 127 | ||
| 129 | /* Parse extra opts if any */ | 128 | /* Parse extra opts if any */ |
| 130 | argv = np_extra_opts (&argc, argv, progname); | 129 | argv = np_extra_opts(&argc, argv, progname); |
| 131 | 130 | ||
| 132 | if (process_arguments (argc, argv) == ERROR) | 131 | if (process_arguments(argc, argv) == ERROR) |
| 133 | usage4 (_("Could not parse arguments")); | 132 | usage4(_("Could not parse arguments")); |
| 134 | 133 | ||
| 135 | /* Set signal handling and alarm */ | 134 | /* Set signal handling and alarm */ |
| 136 | if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { | 135 | if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) { |
| 137 | usage4 (_("Cannot catch SIGALRM")); | 136 | usage4(_("Cannot catch SIGALRM")); |
| 138 | } | 137 | } |
| 139 | alarm (timeout_interval); | 138 | alarm(timeout_interval); |
| 140 | 139 | ||
| 141 | if (verbose > 2) | 140 | if (verbose > 2) |
| 142 | printf ("Initializing DBI\n"); | 141 | printf("Initializing DBI\n"); |
| 143 | 142 | ||
| 144 | dbi_inst *instance_p = { 0 }; | 143 | dbi_inst *instance_p = {0}; |
| 145 | 144 | ||
| 146 | if (dbi_initialize_r(NULL, instance_p) < 0) { | 145 | if (dbi_initialize_r(NULL, instance_p) < 0) { |
| 147 | printf ("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); | 146 | printf("UNKNOWN - failed to initialize DBI; possibly you don't have any drivers installed.\n"); |
| 148 | return STATE_UNKNOWN; | 147 | return STATE_UNKNOWN; |
| 149 | } | 148 | } |
| 150 | 149 | ||
| 151 | if (instance_p == NULL) { | 150 | if (instance_p == NULL) { |
| 152 | printf ("UNKNOWN - failed to initialize DBI.\n"); | 151 | printf("UNKNOWN - failed to initialize DBI.\n"); |
| 153 | return STATE_UNKNOWN; | 152 | return STATE_UNKNOWN; |
| 154 | } | 153 | } |
| 155 | 154 | ||
| 156 | if (verbose) | 155 | if (verbose) |
| 157 | printf ("Opening DBI driver '%s'\n", np_dbi_driver); | 156 | printf("Opening DBI driver '%s'\n", np_dbi_driver); |
| 158 | 157 | ||
| 159 | driver = dbi_driver_open_r(np_dbi_driver, instance_p); | 158 | driver = dbi_driver_open_r(np_dbi_driver, instance_p); |
| 160 | if (! driver) { | 159 | if (!driver) { |
| 161 | printf ("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", | 160 | printf("UNKNOWN - failed to open DBI driver '%s'; possibly it's not installed.\n", np_dbi_driver); |
| 162 | np_dbi_driver); | ||
| 163 | 161 | ||
| 164 | printf ("Known drivers:\n"); | 162 | printf("Known drivers:\n"); |
| 165 | for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { | 163 | for (driver = dbi_driver_list_r(NULL, instance_p); driver; driver = dbi_driver_list_r(driver, instance_p)) { |
| 166 | printf (" - %s\n", dbi_driver_get_name (driver)); | 164 | printf(" - %s\n", dbi_driver_get_name(driver)); |
| 167 | } | 165 | } |
| 168 | return STATE_UNKNOWN; | 166 | return STATE_UNKNOWN; |
| 169 | } | 167 | } |
| 170 | 168 | ||
| 171 | /* make a connection to the database */ | 169 | /* make a connection to the database */ |
| 172 | gettimeofday (&start_timeval, NULL); | 170 | gettimeofday(&start_timeval, NULL); |
| 173 | 171 | ||
| 174 | conn = dbi_conn_open (driver); | 172 | conn = dbi_conn_open(driver); |
| 175 | if (! conn) { | 173 | if (!conn) { |
| 176 | printf ("UNKNOWN - failed top open connection object.\n"); | 174 | printf("UNKNOWN - failed top open connection object.\n"); |
| 177 | dbi_conn_close (conn); | 175 | dbi_conn_close(conn); |
| 178 | return STATE_UNKNOWN; | 176 | return STATE_UNKNOWN; |
| 179 | } | 177 | } |
| 180 | 178 | ||
| @@ -182,210 +180,190 @@ main (int argc, char **argv) | |||
| 182 | const char *opt; | 180 | const char *opt; |
| 183 | 181 | ||
| 184 | if (verbose > 1) | 182 | if (verbose > 1) |
| 185 | printf ("Setting DBI driver option '%s' to '%s'\n", | 183 | printf("Setting DBI driver option '%s' to '%s'\n", np_dbi_options[i].key, np_dbi_options[i].value); |
| 186 | np_dbi_options[i].key, np_dbi_options[i].value); | ||
| 187 | 184 | ||
| 188 | if (! dbi_conn_set_option (conn, np_dbi_options[i].key, np_dbi_options[i].value)) | 185 | if (!dbi_conn_set_option(conn, np_dbi_options[i].key, np_dbi_options[i].value)) |
| 189 | continue; | 186 | continue; |
| 190 | /* else: status != 0 */ | 187 | /* else: status != 0 */ |
| 191 | 188 | ||
| 192 | np_dbi_print_error (conn, "UNKNOWN - failed to set option '%s' to '%s'", | 189 | np_dbi_print_error(conn, "UNKNOWN - failed to set option '%s' to '%s'", np_dbi_options[i].key, np_dbi_options[i].value); |
| 193 | np_dbi_options[i].key, np_dbi_options[i].value); | 190 | printf("Known driver options:\n"); |
| 194 | printf ("Known driver options:\n"); | ||
| 195 | 191 | ||
| 196 | for (opt = dbi_conn_get_option_list (conn, NULL); opt; | 192 | for (opt = dbi_conn_get_option_list(conn, NULL); opt; opt = dbi_conn_get_option_list(conn, opt)) { |
| 197 | opt = dbi_conn_get_option_list (conn, opt)) { | 193 | printf(" - %s\n", opt); |
| 198 | printf (" - %s\n", opt); | ||
| 199 | } | 194 | } |
| 200 | dbi_conn_close (conn); | 195 | dbi_conn_close(conn); |
| 201 | return STATE_UNKNOWN; | 196 | return STATE_UNKNOWN; |
| 202 | } | 197 | } |
| 203 | 198 | ||
| 204 | if (host) { | 199 | if (host) { |
| 205 | if (verbose > 1) | 200 | if (verbose > 1) |
| 206 | printf ("Setting DBI driver option 'host' to '%s'\n", host); | 201 | printf("Setting DBI driver option 'host' to '%s'\n", host); |
| 207 | dbi_conn_set_option (conn, "host", host); | 202 | dbi_conn_set_option(conn, "host", host); |
| 208 | } | 203 | } |
| 209 | 204 | ||
| 210 | if (verbose) { | 205 | if (verbose) { |
| 211 | const char *dbname, *host; | 206 | const char *dbname; |
| 207 | const char *host; | ||
| 212 | 208 | ||
| 213 | dbname = dbi_conn_get_option (conn, "dbname"); | 209 | dbname = dbi_conn_get_option(conn, "dbname"); |
| 214 | host = dbi_conn_get_option (conn, "host"); | 210 | host = dbi_conn_get_option(conn, "host"); |
| 215 | 211 | ||
| 216 | if (! dbname) | 212 | if (!dbname) |
| 217 | dbname = "<unspecified>"; | 213 | dbname = "<unspecified>"; |
| 218 | if (! host) | 214 | if (!host) |
| 219 | host = "<unspecified>"; | 215 | host = "<unspecified>"; |
| 220 | 216 | ||
| 221 | printf ("Connecting to database '%s' at host '%s'\n", | 217 | printf("Connecting to database '%s' at host '%s'\n", dbname, host); |
| 222 | dbname, host); | ||
| 223 | } | 218 | } |
| 224 | 219 | ||
| 225 | if (dbi_conn_connect (conn) < 0) { | 220 | if (dbi_conn_connect(conn) < 0) { |
| 226 | np_dbi_print_error (conn, "UNKNOWN - failed to connect to database"); | 221 | np_dbi_print_error(conn, "UNKNOWN - failed to connect to database"); |
| 227 | return STATE_UNKNOWN; | 222 | return STATE_UNKNOWN; |
| 228 | } | 223 | } |
| 229 | 224 | ||
| 230 | gettimeofday (&end_timeval, NULL); | 225 | gettimeofday(&end_timeval, NULL); |
| 231 | conn_time = timediff (start_timeval, end_timeval); | 226 | conn_time = timediff(start_timeval, end_timeval); |
| 232 | 227 | ||
| 233 | server_version = dbi_conn_get_engine_version (conn); | 228 | server_version = dbi_conn_get_engine_version(conn); |
| 234 | if (verbose) | 229 | if (verbose) |
| 235 | printf ("Connected to server version %u\n", server_version); | 230 | printf("Connected to server version %u\n", server_version); |
| 236 | 231 | ||
| 237 | if (metric == METRIC_SERVER_VERSION) | 232 | if (metric == METRIC_SERVER_VERSION) |
| 238 | status = get_status (server_version, dbi_thresholds); | 233 | status = get_status(server_version, dbi_thresholds); |
| 239 | 234 | ||
| 240 | if (verbose) | 235 | if (verbose) |
| 241 | printf ("Time elapsed: %f\n", conn_time); | 236 | printf("Time elapsed: %f\n", conn_time); |
| 242 | 237 | ||
| 243 | if (metric == METRIC_CONN_TIME) | 238 | if (metric == METRIC_CONN_TIME) |
| 244 | status = get_status (conn_time, dbi_thresholds); | 239 | status = get_status(conn_time, dbi_thresholds); |
| 245 | 240 | ||
| 246 | /* select a database */ | 241 | /* select a database */ |
| 247 | if (np_dbi_database) { | 242 | if (np_dbi_database) { |
| 248 | if (verbose > 1) | 243 | if (verbose > 1) |
| 249 | printf ("Selecting database '%s'\n", np_dbi_database); | 244 | printf("Selecting database '%s'\n", np_dbi_database); |
| 250 | 245 | ||
| 251 | if (dbi_conn_select_db (conn, np_dbi_database)) { | 246 | if (dbi_conn_select_db(conn, np_dbi_database)) { |
| 252 | np_dbi_print_error (conn, "UNKNOWN - failed to select database '%s'", | 247 | np_dbi_print_error(conn, "UNKNOWN - failed to select database '%s'", np_dbi_database); |
| 253 | np_dbi_database); | ||
| 254 | return STATE_UNKNOWN; | 248 | return STATE_UNKNOWN; |
| 255 | } | 249 | } |
| 256 | } | 250 | } |
| 257 | 251 | ||
| 258 | if (np_dbi_query) { | 252 | if (np_dbi_query) { |
| 259 | /* execute query */ | 253 | /* execute query */ |
| 260 | status = do_query (conn, &query_val_str, &query_val, &query_time); | 254 | status = do_query(conn, &query_val_str, &query_val, &query_time); |
| 261 | if (status != STATE_OK) | 255 | if (status != STATE_OK) |
| 262 | /* do_query prints an error message in this case */ | 256 | /* do_query prints an error message in this case */ |
| 263 | return status; | 257 | return status; |
| 264 | 258 | ||
| 265 | if (metric == METRIC_QUERY_RESULT) { | 259 | if (metric == METRIC_QUERY_RESULT) { |
| 266 | if (expect) { | 260 | if (expect) { |
| 267 | if ((! query_val_str) || strcmp (query_val_str, expect)) | 261 | if ((!query_val_str) || strcmp(query_val_str, expect)) |
| 268 | status = STATE_CRITICAL; | 262 | status = STATE_CRITICAL; |
| 269 | else | 263 | else |
| 270 | status = STATE_OK; | 264 | status = STATE_OK; |
| 271 | } | 265 | } else if (expect_re_str) { |
| 272 | else if (expect_re_str) { | ||
| 273 | int err; | 266 | int err; |
| 274 | 267 | ||
| 275 | err = regexec (&expect_re, query_val_str, 0, NULL, /* flags = */ 0); | 268 | err = regexec(&expect_re, query_val_str, 0, NULL, /* flags = */ 0); |
| 276 | if (! err) | 269 | if (!err) |
| 277 | status = STATE_OK; | 270 | status = STATE_OK; |
| 278 | else if (err == REG_NOMATCH) | 271 | else if (err == REG_NOMATCH) |
| 279 | status = STATE_CRITICAL; | 272 | status = STATE_CRITICAL; |
| 280 | else { | 273 | else { |
| 281 | char errmsg[1024]; | 274 | char errmsg[1024]; |
| 282 | regerror (err, &expect_re, errmsg, sizeof (errmsg)); | 275 | regerror(err, &expect_re, errmsg, sizeof(errmsg)); |
| 283 | printf ("ERROR - failed to execute regular expression: %s\n", | 276 | printf("ERROR - failed to execute regular expression: %s\n", errmsg); |
| 284 | errmsg); | ||
| 285 | status = STATE_CRITICAL; | 277 | status = STATE_CRITICAL; |
| 286 | } | 278 | } |
| 287 | } | 279 | } else |
| 288 | else | 280 | status = get_status(query_val, dbi_thresholds); |
| 289 | status = get_status (query_val, dbi_thresholds); | 281 | } else if (metric == METRIC_QUERY_TIME) |
| 290 | } | 282 | status = get_status(query_time, dbi_thresholds); |
| 291 | else if (metric == METRIC_QUERY_TIME) | ||
| 292 | status = get_status (query_time, dbi_thresholds); | ||
| 293 | } | 283 | } |
| 294 | 284 | ||
| 295 | if (verbose) | 285 | if (verbose) |
| 296 | printf("Closing connection\n"); | 286 | printf("Closing connection\n"); |
| 297 | dbi_conn_close (conn); | 287 | dbi_conn_close(conn); |
| 298 | 288 | ||
| 299 | /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error | 289 | /* In case of METRIC_QUERY_RESULT, isnan(query_val) indicates an error |
| 300 | * which should have been reported and handled (abort) before | 290 | * which should have been reported and handled (abort) before |
| 301 | * ... unless we expected a string to be returned */ | 291 | * ... unless we expected a string to be returned */ |
| 302 | assert ((metric != METRIC_QUERY_RESULT) || (! isnan (query_val)) | 292 | assert((metric != METRIC_QUERY_RESULT) || (!isnan(query_val)) || (type == TYPE_STRING)); |
| 303 | || (type == TYPE_STRING)); | ||
| 304 | 293 | ||
| 305 | assert ((type != TYPE_STRING) || (expect || expect_re_str)); | 294 | assert((type != TYPE_STRING) || (expect || expect_re_str)); |
| 306 | 295 | ||
| 307 | printf ("%s - connection time: %fs", state_text (status), conn_time); | 296 | printf("%s - connection time: %fs", state_text(status), conn_time); |
| 308 | if (np_dbi_query) { | 297 | if (np_dbi_query) { |
| 309 | if (type == TYPE_STRING) { | 298 | if (type == TYPE_STRING) { |
| 310 | assert (expect || expect_re_str); | 299 | assert(expect || expect_re_str); |
| 311 | printf (", '%s' returned '%s' in %fs", np_dbi_query, | 300 | printf(", '%s' returned '%s' in %fs", np_dbi_query, query_val_str ? query_val_str : "<nothing>", query_time); |
| 312 | query_val_str ? query_val_str : "<nothing>", query_time); | ||
| 313 | if (status != STATE_OK) { | 301 | if (status != STATE_OK) { |
| 314 | if (expect) | 302 | if (expect) |
| 315 | printf (" (expected '%s')", expect); | 303 | printf(" (expected '%s')", expect); |
| 316 | else if (expect_re_str) | 304 | else if (expect_re_str) |
| 317 | printf (" (expected regex /%s/%s)", expect_re_str, | 305 | printf(" (expected regex /%s/%s)", expect_re_str, ((expect_re_cflags & REG_ICASE) ? "i" : "")); |
| 318 | ((expect_re_cflags & REG_ICASE) ? "i" : "")); | ||
| 319 | } | 306 | } |
| 320 | } | 307 | } else if (isnan(query_val)) |
| 321 | else if (isnan (query_val)) | 308 | printf(", '%s' query execution time: %fs", np_dbi_query, query_time); |
| 322 | printf (", '%s' query execution time: %fs", np_dbi_query, query_time); | ||
| 323 | else | 309 | else |
| 324 | printf (", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); | 310 | printf(", '%s' returned %f in %fs", np_dbi_query, query_val, query_time); |
| 325 | } | 311 | } |
| 326 | 312 | ||
| 327 | printf (" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, | 313 | printf(" | conntime=%fs;%s;%s;0; server_version=%u;%s;%s;0;", conn_time, |
| 328 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", | 314 | ((metric == METRIC_CONN_TIME) && warning_range) ? warning_range : "", |
| 329 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", | 315 | ((metric == METRIC_CONN_TIME) && critical_range) ? critical_range : "", server_version, |
| 330 | server_version, | 316 | ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "", |
| 331 | ((metric == METRIC_SERVER_VERSION) && warning_range) ? warning_range : "", | 317 | ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : ""); |
| 332 | ((metric == METRIC_SERVER_VERSION) && critical_range) ? critical_range : ""); | ||
| 333 | if (np_dbi_query) { | 318 | if (np_dbi_query) { |
| 334 | if (! isnan (query_val)) /* this is also true when -e is used */ | 319 | if (!isnan(query_val)) /* this is also true when -e is used */ |
| 335 | printf (" query=%f;%s;%s;;", query_val, | 320 | printf(" query=%f;%s;%s;;", query_val, ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", |
| 336 | ((metric == METRIC_QUERY_RESULT) && warning_range) ? warning_range : "", | 321 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); |
| 337 | ((metric == METRIC_QUERY_RESULT) && critical_range) ? critical_range : ""); | 322 | printf(" querytime=%fs;%s;%s;0;", query_time, ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "", |
| 338 | printf (" querytime=%fs;%s;%s;0;", query_time, | 323 | ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : ""); |
| 339 | ((metric == METRIC_QUERY_TIME) && warning_range) ? warning_range : "", | ||
| 340 | ((metric == METRIC_QUERY_TIME) && critical_range) ? critical_range : ""); | ||
| 341 | } | 324 | } |
| 342 | printf ("\n"); | 325 | printf("\n"); |
| 343 | return status; | 326 | return status; |
| 344 | } | 327 | } |
| 345 | 328 | ||
| 346 | /* process command-line arguments */ | 329 | /* process command-line arguments */ |
| 347 | int | 330 | int process_arguments(int argc, char **argv) { |
| 348 | process_arguments (int argc, char **argv) | ||
| 349 | { | ||
| 350 | int c; | 331 | int c; |
| 351 | 332 | ||
| 352 | int option = 0; | 333 | int option = 0; |
| 353 | static struct option longopts[] = { | 334 | static struct option longopts[] = {STD_LONG_OPTS, |
| 354 | STD_LONG_OPTS, | 335 | |
| 355 | 336 | {"expect", required_argument, 0, 'e'}, | |
| 356 | {"expect", required_argument, 0, 'e'}, | 337 | {"regex", required_argument, 0, 'r'}, |
| 357 | {"regex", required_argument, 0, 'r'}, | 338 | {"regexi", required_argument, 0, 'R'}, |
| 358 | {"regexi", required_argument, 0, 'R'}, | 339 | {"metric", required_argument, 0, 'm'}, |
| 359 | {"metric", required_argument, 0, 'm'}, | 340 | {"driver", required_argument, 0, 'd'}, |
| 360 | {"driver", required_argument, 0, 'd'}, | 341 | {"option", required_argument, 0, 'o'}, |
| 361 | {"option", required_argument, 0, 'o'}, | 342 | {"query", required_argument, 0, 'q'}, |
| 362 | {"query", required_argument, 0, 'q'}, | 343 | {"database", required_argument, 0, 'D'}, |
| 363 | {"database", required_argument, 0, 'D'}, | 344 | {0, 0, 0, 0}}; |
| 364 | {0, 0, 0, 0} | ||
| 365 | }; | ||
| 366 | 345 | ||
| 367 | while (1) { | 346 | while (1) { |
| 368 | c = getopt_long (argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", | 347 | c = getopt_long(argc, argv, "Vvht:c:w:e:r:R:m:H:d:o:q:D:", longopts, &option); |
| 369 | longopts, &option); | ||
| 370 | 348 | ||
| 371 | if (c == EOF) | 349 | if (c == EOF) |
| 372 | break; | 350 | break; |
| 373 | 351 | ||
| 374 | switch (c) { | 352 | switch (c) { |
| 375 | case '?': /* usage */ | 353 | case '?': /* usage */ |
| 376 | usage5 (); | 354 | usage5(); |
| 377 | case 'h': /* help */ | 355 | case 'h': /* help */ |
| 378 | print_help (); | 356 | print_help(); |
| 379 | exit (STATE_UNKNOWN); | 357 | exit(STATE_UNKNOWN); |
| 380 | case 'V': /* version */ | 358 | case 'V': /* version */ |
| 381 | print_revision (progname, NP_VERSION); | 359 | print_revision(progname, NP_VERSION); |
| 382 | exit (STATE_UNKNOWN); | 360 | exit(STATE_UNKNOWN); |
| 383 | 361 | ||
| 384 | case 'c': /* critical range */ | 362 | case 'c': /* critical range */ |
| 385 | critical_range = optarg; | 363 | critical_range = optarg; |
| 386 | type = TYPE_NUMERIC; | 364 | type = TYPE_NUMERIC; |
| 387 | break; | 365 | break; |
| 388 | case 'w': /* warning range */ | 366 | case 'w': /* warning range */ |
| 389 | warning_range = optarg; | 367 | warning_range = optarg; |
| 390 | type = TYPE_NUMERIC; | 368 | type = TYPE_NUMERIC; |
| 391 | break; | 369 | break; |
| @@ -396,47 +374,45 @@ process_arguments (int argc, char **argv) | |||
| 396 | case 'R': | 374 | case 'R': |
| 397 | expect_re_cflags = REG_ICASE; | 375 | expect_re_cflags = REG_ICASE; |
| 398 | /* fall through */ | 376 | /* fall through */ |
| 399 | case 'r': | 377 | case 'r': { |
| 400 | { | 378 | int err; |
| 401 | int err; | ||
| 402 | 379 | ||
| 403 | expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; | 380 | expect_re_cflags |= REG_EXTENDED | REG_NOSUB | REG_NEWLINE; |
| 404 | expect_re_str = optarg; | 381 | expect_re_str = optarg; |
| 405 | type = TYPE_STRING; | 382 | type = TYPE_STRING; |
| 406 | 383 | ||
| 407 | err = regcomp (&expect_re, expect_re_str, expect_re_cflags); | 384 | err = regcomp(&expect_re, expect_re_str, expect_re_cflags); |
| 408 | if (err) { | 385 | if (err) { |
| 409 | char errmsg[1024]; | 386 | char errmsg[1024]; |
| 410 | regerror (err, &expect_re, errmsg, sizeof (errmsg)); | 387 | regerror(err, &expect_re, errmsg, sizeof(errmsg)); |
| 411 | printf ("ERROR - failed to compile regular expression: %s\n", | 388 | printf("ERROR - failed to compile regular expression: %s\n", errmsg); |
| 412 | errmsg); | 389 | return ERROR; |
| 413 | return ERROR; | ||
| 414 | } | ||
| 415 | break; | ||
| 416 | } | 390 | } |
| 391 | break; | ||
| 392 | } | ||
| 417 | 393 | ||
| 418 | case 'm': | 394 | case 'm': |
| 419 | if (! strcasecmp (optarg, "CONN_TIME")) | 395 | if (!strcasecmp(optarg, "CONN_TIME")) |
| 420 | metric = METRIC_CONN_TIME; | 396 | metric = METRIC_CONN_TIME; |
| 421 | else if (! strcasecmp (optarg, "SERVER_VERSION")) | 397 | else if (!strcasecmp(optarg, "SERVER_VERSION")) |
| 422 | metric = METRIC_SERVER_VERSION; | 398 | metric = METRIC_SERVER_VERSION; |
| 423 | else if (! strcasecmp (optarg, "QUERY_RESULT")) | 399 | else if (!strcasecmp(optarg, "QUERY_RESULT")) |
| 424 | metric = METRIC_QUERY_RESULT; | 400 | metric = METRIC_QUERY_RESULT; |
| 425 | else if (! strcasecmp (optarg, "QUERY_TIME")) | 401 | else if (!strcasecmp(optarg, "QUERY_TIME")) |
| 426 | metric = METRIC_QUERY_TIME; | 402 | metric = METRIC_QUERY_TIME; |
| 427 | else | 403 | else |
| 428 | usage2 (_("Invalid metric"), optarg); | 404 | usage2(_("Invalid metric"), optarg); |
| 429 | break; | 405 | break; |
| 430 | case 't': /* timeout */ | 406 | case 't': /* timeout */ |
| 431 | if (!is_intnonneg (optarg)) | 407 | if (!is_intnonneg(optarg)) |
| 432 | usage2 (_("Timeout interval must be a positive integer"), optarg); | 408 | usage2(_("Timeout interval must be a positive integer"), optarg); |
| 433 | else | 409 | else |
| 434 | timeout_interval = atoi (optarg); | 410 | timeout_interval = atoi(optarg); |
| 435 | 411 | ||
| 436 | break; | 412 | break; |
| 437 | case 'H': /* host */ | 413 | case 'H': /* host */ |
| 438 | if (!is_host (optarg)) | 414 | if (!is_host(optarg)) |
| 439 | usage2 (_("Invalid hostname/address"), optarg); | 415 | usage2(_("Invalid hostname/address"), optarg); |
| 440 | else | 416 | else |
| 441 | host = optarg; | 417 | host = optarg; |
| 442 | break; | 418 | break; |
| @@ -447,36 +423,34 @@ process_arguments (int argc, char **argv) | |||
| 447 | case 'd': | 423 | case 'd': |
| 448 | np_dbi_driver = optarg; | 424 | np_dbi_driver = optarg; |
| 449 | break; | 425 | break; |
| 450 | case 'o': | 426 | case 'o': { |
| 451 | { | 427 | driver_option_t *new; |
| 452 | driver_option_t *new; | ||
| 453 | 428 | ||
| 454 | char *k, *v; | 429 | char *k; |
| 430 | char *v; | ||
| 455 | 431 | ||
| 456 | k = optarg; | 432 | k = optarg; |
| 457 | v = strchr (k, (int)'='); | 433 | v = strchr(k, (int)'='); |
| 458 | 434 | ||
| 459 | if (! v) | 435 | if (!v) |
| 460 | usage2 (_("Option must be '<key>=<value>'"), optarg); | 436 | usage2(_("Option must be '<key>=<value>'"), optarg); |
| 461 | 437 | ||
| 462 | *v = '\0'; | 438 | *v = '\0'; |
| 463 | ++v; | 439 | ++v; |
| 464 | 440 | ||
| 465 | new = realloc (np_dbi_options, | 441 | new = realloc(np_dbi_options, (np_dbi_options_num + 1) * sizeof(*new)); |
| 466 | (np_dbi_options_num + 1) * sizeof (*new)); | 442 | if (!new) { |
| 467 | if (! new) { | 443 | printf("UNKNOWN - failed to reallocate memory\n"); |
| 468 | printf ("UNKNOWN - failed to reallocate memory\n"); | 444 | exit(STATE_UNKNOWN); |
| 469 | exit (STATE_UNKNOWN); | 445 | } |
| 470 | } | ||
| 471 | 446 | ||
| 472 | np_dbi_options = new; | 447 | np_dbi_options = new; |
| 473 | new = np_dbi_options + np_dbi_options_num; | 448 | new = np_dbi_options + np_dbi_options_num; |
| 474 | ++np_dbi_options_num; | 449 | ++np_dbi_options_num; |
| 475 | 450 | ||
| 476 | new->key = k; | 451 | new->key = k; |
| 477 | new->value = v; | 452 | new->value = v; |
| 478 | } | 453 | } break; |
| 479 | break; | ||
| 480 | case 'q': | 454 | case 'q': |
| 481 | np_dbi_query = optarg; | 455 | np_dbi_query = optarg; |
| 482 | break; | 456 | break; |
| @@ -486,341 +460,314 @@ process_arguments (int argc, char **argv) | |||
| 486 | } | 460 | } |
| 487 | } | 461 | } |
| 488 | 462 | ||
| 489 | set_thresholds (&dbi_thresholds, warning_range, critical_range); | 463 | set_thresholds(&dbi_thresholds, warning_range, critical_range); |
| 490 | 464 | ||
| 491 | return validate_arguments (); | 465 | return validate_arguments(); |
| 492 | } | 466 | } |
| 493 | 467 | ||
| 494 | int | 468 | int validate_arguments(void) { |
| 495 | validate_arguments () | 469 | if (!np_dbi_driver) |
| 496 | { | 470 | usage("Must specify a DBI driver"); |
| 497 | if (! np_dbi_driver) | ||
| 498 | usage ("Must specify a DBI driver"); | ||
| 499 | 471 | ||
| 500 | if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) | 472 | if (((metric == METRIC_QUERY_RESULT) || (metric == METRIC_QUERY_TIME)) && (!np_dbi_query)) |
| 501 | && (! np_dbi_query)) | 473 | usage("Must specify a query to execute (metric == QUERY_RESULT)"); |
| 502 | usage ("Must specify a query to execute (metric == QUERY_RESULT)"); | ||
| 503 | 474 | ||
| 504 | if ((metric != METRIC_CONN_TIME) | 475 | if ((metric != METRIC_CONN_TIME) && (metric != METRIC_SERVER_VERSION) && (metric != METRIC_QUERY_RESULT) && |
| 505 | && (metric != METRIC_SERVER_VERSION) | 476 | (metric != METRIC_QUERY_TIME)) |
| 506 | && (metric != METRIC_QUERY_RESULT) | 477 | usage("Invalid metric specified"); |
| 507 | && (metric != METRIC_QUERY_TIME)) | ||
| 508 | usage ("Invalid metric specified"); | ||
| 509 | 478 | ||
| 510 | if (expect && (warning_range || critical_range || expect_re_str)) | 479 | if (expect && (warning_range || critical_range || expect_re_str)) |
| 511 | usage ("Do not mix -e and -w/-c/-r/-R"); | 480 | usage("Do not mix -e and -w/-c/-r/-R"); |
| 512 | 481 | ||
| 513 | if (expect_re_str && (warning_range || critical_range || expect)) | 482 | if (expect_re_str && (warning_range || critical_range || expect)) |
| 514 | usage ("Do not mix -r/-R and -w/-c/-e"); | 483 | usage("Do not mix -r/-R and -w/-c/-e"); |
| 515 | 484 | ||
| 516 | if (expect && (metric != METRIC_QUERY_RESULT)) | 485 | if (expect && (metric != METRIC_QUERY_RESULT)) |
| 517 | usage ("Option -e requires metric QUERY_RESULT"); | 486 | usage("Option -e requires metric QUERY_RESULT"); |
| 518 | 487 | ||
| 519 | if (expect_re_str && (metric != METRIC_QUERY_RESULT)) | 488 | if (expect_re_str && (metric != METRIC_QUERY_RESULT)) |
| 520 | usage ("Options -r/-R require metric QUERY_RESULT"); | 489 | usage("Options -r/-R require metric QUERY_RESULT"); |
| 521 | 490 | ||
| 522 | return OK; | 491 | return OK; |
| 523 | } | 492 | } |
| 524 | 493 | ||
| 525 | void | 494 | void print_help(void) { |
| 526 | print_help (void) | 495 | print_revision(progname, NP_VERSION); |
| 527 | { | ||
| 528 | print_revision (progname, NP_VERSION); | ||
| 529 | 496 | ||
| 530 | printf (COPYRIGHT, copyright, email); | 497 | printf(COPYRIGHT, copyright, email); |
| 531 | 498 | ||
| 532 | printf (_("This program connects to an (SQL) database using DBI and checks the\n" | 499 | printf(_("This program connects to an (SQL) database using DBI and checks the\n" |
| 533 | "specified metric against threshold levels. The default metric is\n" | 500 | "specified metric against threshold levels. The default metric is\n" |
| 534 | "the result of the specified query.\n")); | 501 | "the result of the specified query.\n")); |
| 535 | 502 | ||
| 536 | printf ("\n\n"); | 503 | printf("\n\n"); |
| 537 | 504 | ||
| 538 | print_usage (); | 505 | print_usage(); |
| 539 | 506 | ||
| 540 | printf (UT_HELP_VRSN); | 507 | printf(UT_HELP_VRSN); |
| 541 | /* include this conditionally to avoid 'zero-length printf format string' | 508 | /* include this conditionally to avoid 'zero-length printf format string' |
| 542 | * compiler warnings */ | 509 | * compiler warnings */ |
| 543 | #ifdef NP_EXTRA_OPTS | 510 | #ifdef NP_EXTRA_OPTS |
| 544 | printf (UT_EXTRA_OPTS); | 511 | printf(UT_EXTRA_OPTS); |
| 545 | #endif | 512 | #endif |
| 546 | printf ("\n"); | 513 | printf("\n"); |
| 547 | 514 | ||
| 548 | printf (" %s\n", "-d, --driver=STRING"); | 515 | printf(" %s\n", "-d, --driver=STRING"); |
| 549 | printf (" %s\n", _("DBI driver to use")); | 516 | printf(" %s\n", _("DBI driver to use")); |
| 550 | printf (" %s\n", "-o, --option=STRING"); | 517 | printf(" %s\n", "-o, --option=STRING"); |
| 551 | printf (" %s\n", _("DBI driver options")); | 518 | printf(" %s\n", _("DBI driver options")); |
| 552 | printf (" %s\n", "-q, --query=STRING"); | 519 | printf(" %s\n", "-q, --query=STRING"); |
| 553 | printf (" %s\n", _("query to execute")); | 520 | printf(" %s\n", _("query to execute")); |
| 554 | printf ("\n"); | 521 | printf("\n"); |
| 555 | 522 | ||
| 556 | printf (UT_WARN_CRIT_RANGE); | 523 | printf(UT_WARN_CRIT_RANGE); |
| 557 | printf (" %s\n", "-e, --expect=STRING"); | 524 | printf(" %s\n", "-e, --expect=STRING"); |
| 558 | printf (" %s\n", _("String to expect as query result")); | 525 | printf(" %s\n", _("String to expect as query result")); |
| 559 | printf (" %s\n", _("Do not mix with -w, -c, -r, or -R!")); | 526 | printf(" %s\n", _("Do not mix with -w, -c, -r, or -R!")); |
| 560 | printf (" %s\n", "-r, --regex=REGEX"); | 527 | printf(" %s\n", "-r, --regex=REGEX"); |
| 561 | printf (" %s\n", _("Extended POSIX regular expression to check query result against")); | 528 | printf(" %s\n", _("Extended POSIX regular expression to check query result against")); |
| 562 | printf (" %s\n", _("Do not mix with -w, -c, -e, or -R!")); | 529 | printf(" %s\n", _("Do not mix with -w, -c, -e, or -R!")); |
| 563 | printf (" %s\n", "-R, --regexi=REGEX"); | 530 | printf(" %s\n", "-R, --regexi=REGEX"); |
| 564 | printf (" %s\n", _("Case-insensitive extended POSIX regex to check query result against")); | 531 | printf(" %s\n", _("Case-insensitive extended POSIX regex to check query result against")); |
| 565 | printf (" %s\n", _("Do not mix with -w, -c, -e, or -r!")); | 532 | printf(" %s\n", _("Do not mix with -w, -c, -e, or -r!")); |
| 566 | printf (" %s\n", "-m, --metric=METRIC"); | 533 | printf(" %s\n", "-m, --metric=METRIC"); |
| 567 | printf (" %s\n", _("Metric to check thresholds against. Available metrics:")); | 534 | printf(" %s\n", _("Metric to check thresholds against. Available metrics:")); |
| 568 | printf (" CONN_TIME - %s\n", _("time used for setting up the database connection")); | 535 | printf(" CONN_TIME - %s\n", _("time used for setting up the database connection")); |
| 569 | printf (" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); | 536 | printf(" QUERY_RESULT - %s\n", _("result (first column of first row) of the query")); |
| 570 | printf (" QUERY_TIME - %s\n", _("time used to execute the query")); | 537 | printf(" QUERY_TIME - %s\n", _("time used to execute the query")); |
| 571 | printf (" %s\n", _("(ignore the query result)")); | 538 | printf(" %s\n", _("(ignore the query result)")); |
| 572 | printf ("\n"); | 539 | printf("\n"); |
| 573 | 540 | ||
| 574 | printf (UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); | 541 | printf(UT_CONN_TIMEOUT, DEFAULT_SOCKET_TIMEOUT); |
| 575 | 542 | ||
| 576 | printf (UT_VERBOSE); | 543 | printf(UT_VERBOSE); |
| 577 | 544 | ||
| 578 | printf ("\n"); | 545 | printf("\n"); |
| 579 | printf (" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates")); | 546 | printf(" %s\n", _("A DBI driver (-d option) is required. If the specified metric operates")); |
| 580 | printf (" %s\n\n", _("on a query, one has to be specified (-q option).")); | 547 | printf(" %s\n\n", _("on a query, one has to be specified (-q option).")); |
| 581 | 548 | ||
| 582 | printf (" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,")); | 549 | printf(" %s\n", _("This plugin connects to an (SQL) database using libdbi and, optionally,")); |
| 583 | printf (" %s\n", _("executes the specified query. The first column of the first row of the")); | 550 | printf(" %s\n", _("executes the specified query. The first column of the first row of the")); |
| 584 | printf (" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the")); | 551 | printf(" %s\n", _("result will be parsed and, in QUERY_RESULT mode, compared with the")); |
| 585 | printf (" %s\n", _("warning and critical ranges. The result from the query has to be numeric")); | 552 | printf(" %s\n", _("warning and critical ranges. The result from the query has to be numeric")); |
| 586 | printf (" %s\n\n", _("(strings representing numbers are fine).")); | 553 | printf(" %s\n\n", _("(strings representing numbers are fine).")); |
| 587 | 554 | ||
| 588 | printf (" %s\n", _("The number and type of required DBI driver options depends on the actual")); | 555 | printf(" %s\n", _("The number and type of required DBI driver options depends on the actual")); |
| 589 | printf (" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/")); | 556 | printf(" %s\n", _("driver. See its documentation at http://libdbi-drivers.sourceforge.net/")); |
| 590 | printf (" %s\n\n", _("for details.")); | 557 | printf(" %s\n\n", _("for details.")); |
| 591 | 558 | ||
| 592 | printf (" %s\n", _("Examples:")); | 559 | printf(" %s\n", _("Examples:")); |
| 593 | printf (" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n"); | 560 | printf(" check_dbi -d pgsql -o username=postgres -m QUERY_RESULT \\\n"); |
| 594 | printf (" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n"); | 561 | printf(" -q 'SELECT COUNT(*) FROM pg_stat_activity' -w 5 -c 10\n"); |
| 595 | printf (" Warning if more than five connections; critical if more than ten.\n\n"); | 562 | printf(" Warning if more than five connections; critical if more than ten.\n\n"); |
| 596 | 563 | ||
| 597 | printf (" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n"); | 564 | printf(" check_dbi -d mysql -H localhost -o username=user -o password=secret \\\n"); |
| 598 | printf (" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n"); | 565 | printf(" -q 'SELECT COUNT(*) FROM logged_in_users -w 5:20 -c 0:50\n"); |
| 599 | printf (" Warning if less than 5 or more than 20 users are logged in; critical\n"); | 566 | printf(" Warning if less than 5 or more than 20 users are logged in; critical\n"); |
| 600 | printf (" if more than 50 users.\n\n"); | 567 | printf(" if more than 50 users.\n\n"); |
| 601 | 568 | ||
| 602 | printf (" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n"); | 569 | printf(" check_dbi -d firebird -o username=user -o password=secret -o dbname=foo \\\n"); |
| 603 | printf (" -m CONN_TIME -w 0.5 -c 2\n"); | 570 | printf(" -m CONN_TIME -w 0.5 -c 2\n"); |
| 604 | printf (" Warning if connecting to the database takes more than half of a second;\n"); | 571 | printf(" Warning if connecting to the database takes more than half of a second;\n"); |
| 605 | printf (" critical if it takes more than 2 seconds.\n\n"); | 572 | printf(" critical if it takes more than 2 seconds.\n\n"); |
| 606 | 573 | ||
| 607 | printf (" check_dbi -d mysql -H localhost -o username=user \\\n"); | 574 | printf(" check_dbi -d mysql -H localhost -o username=user \\\n"); |
| 608 | printf (" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n"); | 575 | printf(" -q 'SELECT concat(@@version, \" \", @@version_comment)' \\\n"); |
| 609 | printf (" -r '^5\\.[01].*MySQL Enterprise Server'\n"); | 576 | printf(" -r '^5\\.[01].*MySQL Enterprise Server'\n"); |
| 610 | printf (" Critical if the database server is not a MySQL enterprise server in either\n"); | 577 | printf(" Critical if the database server is not a MySQL enterprise server in either\n"); |
| 611 | printf (" version 5.0.x or 5.1.x.\n\n"); | 578 | printf(" version 5.0.x or 5.1.x.\n\n"); |
| 612 | 579 | ||
| 613 | printf (" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n"); | 580 | printf(" check_dbi -d pgsql -u username=user -m SERVER_VERSION \\\n"); |
| 614 | printf (" -w 090000:090099 -c 090000:090199\n"); | 581 | printf(" -w 090000:090099 -c 090000:090199\n"); |
| 615 | printf (" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n"); | 582 | printf(" Warn if the PostgreSQL server version is not 9.0.x; critical if the version\n"); |
| 616 | printf (" is less than 9.x or higher than 9.1.x.\n"); | 583 | printf(" is less than 9.x or higher than 9.1.x.\n"); |
| 617 | 584 | ||
| 618 | printf (UT_SUPPORT); | 585 | printf(UT_SUPPORT); |
| 619 | } | 586 | } |
| 620 | 587 | ||
| 621 | void | 588 | void print_usage(void) { |
| 622 | print_usage (void) | 589 | printf("%s\n", _("Usage:")); |
| 623 | { | 590 | printf("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); |
| 624 | printf ("%s\n", _("Usage:")); | 591 | printf(" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); |
| 625 | printf ("%s -d <DBI driver> [-o <DBI driver option> [...]] [-q <query>]\n", progname); | 592 | printf(" [-e <string>] [-r|-R <regex>]\n"); |
| 626 | printf (" [-H <host>] [-c <critical range>] [-w <warning range>] [-m <metric>]\n"); | ||
| 627 | printf (" [-e <string>] [-r|-R <regex>]\n"); | ||
| 628 | } | 593 | } |
| 629 | 594 | ||
| 630 | #define CHECK_IGNORE_ERROR(s) \ | 595 | #define CHECK_IGNORE_ERROR(s) \ |
| 631 | do { \ | 596 | do { \ |
| 632 | if (metric != METRIC_QUERY_RESULT) \ | 597 | if (metric != METRIC_QUERY_RESULT) \ |
| 633 | return (s); \ | 598 | return (s); \ |
| 634 | } while (0) | 599 | } while (0) |
| 635 | 600 | ||
| 636 | const char * | 601 | const char *get_field_str(dbi_conn conn, dbi_result res, unsigned short field_type) { |
| 637 | get_field_str (dbi_conn conn, dbi_result res, unsigned short field_type) | ||
| 638 | { | ||
| 639 | const char *str; | 602 | const char *str; |
| 640 | 603 | ||
| 641 | if (field_type != DBI_TYPE_STRING) { | 604 | if (field_type != DBI_TYPE_STRING) { |
| 642 | printf ("CRITICAL - result value is not a string\n"); | 605 | printf("CRITICAL - result value is not a string\n"); |
| 643 | return NULL; | 606 | return NULL; |
| 644 | } | 607 | } |
| 645 | 608 | ||
| 646 | str = dbi_result_get_string_idx (res, 1); | 609 | str = dbi_result_get_string_idx(res, 1); |
| 647 | if ((! str) || (strcmp (str, "ERROR") == 0)) { | 610 | if ((!str) || (strcmp(str, "ERROR") == 0)) { |
| 648 | CHECK_IGNORE_ERROR (NULL); | 611 | CHECK_IGNORE_ERROR(NULL); |
| 649 | np_dbi_print_error (conn, "CRITICAL - failed to fetch string value"); | 612 | np_dbi_print_error(conn, "CRITICAL - failed to fetch string value"); |
| 650 | return NULL; | 613 | return NULL; |
| 651 | } | 614 | } |
| 652 | 615 | ||
| 653 | if ((verbose && (type == TYPE_STRING)) || (verbose > 2)) | 616 | if ((verbose && (type == TYPE_STRING)) || (verbose > 2)) |
| 654 | printf ("Query returned string '%s'\n", str); | 617 | printf("Query returned string '%s'\n", str); |
| 655 | return str; | 618 | return str; |
| 656 | } | 619 | } |
| 657 | 620 | ||
| 658 | double | 621 | double get_field(dbi_conn conn, dbi_result res, unsigned short *field_type) { |
| 659 | get_field (dbi_conn conn, dbi_result res, unsigned short *field_type) | ||
| 660 | { | ||
| 661 | double val = NAN; | 622 | double val = NAN; |
| 662 | 623 | ||
| 663 | if (*field_type == DBI_TYPE_INTEGER) { | 624 | if (*field_type == DBI_TYPE_INTEGER) { |
| 664 | val = (double)dbi_result_get_longlong_idx (res, 1); | 625 | val = (double)dbi_result_get_longlong_idx(res, 1); |
| 665 | } | 626 | } else if (*field_type == DBI_TYPE_DECIMAL) { |
| 666 | else if (*field_type == DBI_TYPE_DECIMAL) { | 627 | val = dbi_result_get_double_idx(res, 1); |
| 667 | val = dbi_result_get_double_idx (res, 1); | 628 | } else if (*field_type == DBI_TYPE_STRING) { |
| 668 | } | ||
| 669 | else if (*field_type == DBI_TYPE_STRING) { | ||
| 670 | const char *val_str; | 629 | const char *val_str; |
| 671 | char *endptr = NULL; | 630 | char *endptr = NULL; |
| 672 | 631 | ||
| 673 | val_str = get_field_str (conn, res, *field_type); | 632 | val_str = get_field_str(conn, res, *field_type); |
| 674 | if (! val_str) { | 633 | if (!val_str) { |
| 675 | CHECK_IGNORE_ERROR (NAN); | 634 | CHECK_IGNORE_ERROR(NAN); |
| 676 | *field_type = DBI_TYPE_ERROR; | 635 | *field_type = DBI_TYPE_ERROR; |
| 677 | return NAN; | 636 | return NAN; |
| 678 | } | 637 | } |
| 679 | 638 | ||
| 680 | val = strtod (val_str, &endptr); | 639 | val = strtod(val_str, &endptr); |
| 681 | if (endptr == val_str) { | 640 | if (endptr == val_str) { |
| 682 | CHECK_IGNORE_ERROR (NAN); | 641 | CHECK_IGNORE_ERROR(NAN); |
| 683 | printf ("CRITICAL - result value is not a numeric: %s\n", val_str); | 642 | printf("CRITICAL - result value is not a numeric: %s\n", val_str); |
| 684 | *field_type = DBI_TYPE_ERROR; | 643 | *field_type = DBI_TYPE_ERROR; |
| 685 | return NAN; | 644 | return NAN; |
| 686 | } | 645 | } |
| 687 | else if ((endptr != NULL) && (*endptr != '\0')) { | 646 | if ((endptr != NULL) && (*endptr != '\0')) { |
| 688 | if (verbose) | 647 | if (verbose) |
| 689 | printf ("Garbage after value: %s\n", endptr); | 648 | printf("Garbage after value: %s\n", endptr); |
| 690 | } | 649 | } |
| 691 | } | 650 | } else { |
| 692 | else { | 651 | CHECK_IGNORE_ERROR(NAN); |
| 693 | CHECK_IGNORE_ERROR (NAN); | 652 | printf("CRITICAL - cannot parse value of type %s (%i)\n", |
| 694 | printf ("CRITICAL - cannot parse value of type %s (%i)\n", | 653 | (*field_type == DBI_TYPE_BINARY) ? "BINARY" |
| 695 | (*field_type == DBI_TYPE_BINARY) | 654 | : (*field_type == DBI_TYPE_DATETIME) ? "DATETIME" |
| 696 | ? "BINARY" | 655 | : "<unknown>", |
| 697 | : (*field_type == DBI_TYPE_DATETIME) | 656 | *field_type); |
| 698 | ? "DATETIME" | ||
| 699 | : "<unknown>", | ||
| 700 | *field_type); | ||
| 701 | *field_type = DBI_TYPE_ERROR; | 657 | *field_type = DBI_TYPE_ERROR; |
| 702 | return NAN; | 658 | return NAN; |
| 703 | } | 659 | } |
| 704 | return val; | 660 | return val; |
| 705 | } | 661 | } |
| 706 | 662 | ||
| 707 | double | 663 | double get_query_result(dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) { |
| 708 | get_query_result (dbi_conn conn, dbi_result res, const char **res_val_str, double *res_val) | ||
| 709 | { | ||
| 710 | unsigned short field_type; | 664 | unsigned short field_type; |
| 711 | double val = NAN; | 665 | double val = NAN; |
| 712 | 666 | ||
| 713 | if (dbi_result_get_numrows (res) == DBI_ROW_ERROR) { | 667 | if (dbi_result_get_numrows(res) == DBI_ROW_ERROR) { |
| 714 | CHECK_IGNORE_ERROR (STATE_OK); | 668 | CHECK_IGNORE_ERROR(STATE_OK); |
| 715 | np_dbi_print_error (conn, "CRITICAL - failed to fetch rows"); | 669 | np_dbi_print_error(conn, "CRITICAL - failed to fetch rows"); |
| 716 | return STATE_CRITICAL; | 670 | return STATE_CRITICAL; |
| 717 | } | 671 | } |
| 718 | 672 | ||
| 719 | if (dbi_result_get_numrows (res) < 1) { | 673 | if (dbi_result_get_numrows(res) < 1) { |
| 720 | CHECK_IGNORE_ERROR (STATE_OK); | 674 | CHECK_IGNORE_ERROR(STATE_OK); |
| 721 | printf ("WARNING - no rows returned\n"); | 675 | printf("WARNING - no rows returned\n"); |
| 722 | return STATE_WARNING; | 676 | return STATE_WARNING; |
| 723 | } | 677 | } |
| 724 | 678 | ||
| 725 | if (dbi_result_get_numfields (res) == DBI_FIELD_ERROR) { | 679 | if (dbi_result_get_numfields(res) == DBI_FIELD_ERROR) { |
| 726 | CHECK_IGNORE_ERROR (STATE_OK); | 680 | CHECK_IGNORE_ERROR(STATE_OK); |
| 727 | np_dbi_print_error (conn, "CRITICAL - failed to fetch fields"); | 681 | np_dbi_print_error(conn, "CRITICAL - failed to fetch fields"); |
| 728 | return STATE_CRITICAL; | 682 | return STATE_CRITICAL; |
| 729 | } | 683 | } |
| 730 | 684 | ||
| 731 | if (dbi_result_get_numfields (res) < 1) { | 685 | if (dbi_result_get_numfields(res) < 1) { |
| 732 | CHECK_IGNORE_ERROR (STATE_OK); | 686 | CHECK_IGNORE_ERROR(STATE_OK); |
| 733 | printf ("WARNING - no fields returned\n"); | 687 | printf("WARNING - no fields returned\n"); |
| 734 | return STATE_WARNING; | 688 | return STATE_WARNING; |
| 735 | } | 689 | } |
| 736 | 690 | ||
| 737 | if (dbi_result_first_row (res) != 1) { | 691 | if (dbi_result_first_row(res) != 1) { |
| 738 | CHECK_IGNORE_ERROR (STATE_OK); | 692 | CHECK_IGNORE_ERROR(STATE_OK); |
| 739 | np_dbi_print_error (conn, "CRITICAL - failed to fetch first row"); | 693 | np_dbi_print_error(conn, "CRITICAL - failed to fetch first row"); |
| 740 | return STATE_CRITICAL; | 694 | return STATE_CRITICAL; |
| 741 | } | 695 | } |
| 742 | 696 | ||
| 743 | field_type = dbi_result_get_field_type_idx (res, 1); | 697 | field_type = dbi_result_get_field_type_idx(res, 1); |
| 744 | if (field_type != DBI_TYPE_ERROR) { | 698 | if (field_type != DBI_TYPE_ERROR) { |
| 745 | if (type == TYPE_STRING) | 699 | if (type == TYPE_STRING) |
| 746 | /* the value will be freed in dbi_result_free */ | 700 | /* the value will be freed in dbi_result_free */ |
| 747 | *res_val_str = strdup (get_field_str (conn, res, field_type)); | 701 | *res_val_str = strdup(get_field_str(conn, res, field_type)); |
| 748 | else | 702 | else |
| 749 | val = get_field (conn, res, &field_type); | 703 | val = get_field(conn, res, &field_type); |
| 750 | } | 704 | } |
| 751 | 705 | ||
| 752 | *res_val = val; | 706 | *res_val = val; |
| 753 | 707 | ||
| 754 | if (field_type == DBI_TYPE_ERROR) { | 708 | if (field_type == DBI_TYPE_ERROR) { |
| 755 | CHECK_IGNORE_ERROR (STATE_OK); | 709 | CHECK_IGNORE_ERROR(STATE_OK); |
| 756 | np_dbi_print_error (conn, "CRITICAL - failed to fetch data"); | 710 | np_dbi_print_error(conn, "CRITICAL - failed to fetch data"); |
| 757 | return STATE_CRITICAL; | 711 | return STATE_CRITICAL; |
| 758 | } | 712 | } |
| 759 | 713 | ||
| 760 | dbi_result_free (res); | 714 | dbi_result_free(res); |
| 761 | return STATE_OK; | 715 | return STATE_OK; |
| 762 | } | 716 | } |
| 763 | 717 | ||
| 764 | #undef CHECK_IGNORE_ERROR | 718 | #undef CHECK_IGNORE_ERROR |
| 765 | 719 | ||
| 766 | int | 720 | int do_query(dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) { |
| 767 | do_query (dbi_conn conn, const char **res_val_str, double *res_val, double *res_time) | ||
| 768 | { | ||
| 769 | dbi_result res; | 721 | dbi_result res; |
| 770 | 722 | ||
| 771 | struct timeval timeval_start, timeval_end; | 723 | struct timeval timeval_start; |
| 724 | struct timeval timeval_end; | ||
| 772 | int status = STATE_OK; | 725 | int status = STATE_OK; |
| 773 | 726 | ||
| 774 | assert (np_dbi_query); | 727 | assert(np_dbi_query); |
| 775 | 728 | ||
| 776 | if (verbose) | 729 | if (verbose) |
| 777 | printf ("Executing query '%s'\n", np_dbi_query); | 730 | printf("Executing query '%s'\n", np_dbi_query); |
| 778 | 731 | ||
| 779 | gettimeofday (&timeval_start, NULL); | 732 | gettimeofday(&timeval_start, NULL); |
| 780 | 733 | ||
| 781 | res = dbi_conn_query (conn, np_dbi_query); | 734 | res = dbi_conn_query(conn, np_dbi_query); |
| 782 | if (! res) { | 735 | if (!res) { |
| 783 | np_dbi_print_error (conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); | 736 | np_dbi_print_error(conn, "CRITICAL - failed to execute query '%s'", np_dbi_query); |
| 784 | return STATE_CRITICAL; | 737 | return STATE_CRITICAL; |
| 785 | } | 738 | } |
| 786 | 739 | ||
| 787 | status = get_query_result (conn, res, res_val_str, res_val); | 740 | status = get_query_result(conn, res, res_val_str, res_val); |
| 788 | 741 | ||
| 789 | gettimeofday (&timeval_end, NULL); | 742 | gettimeofday(&timeval_end, NULL); |
| 790 | *res_time = timediff (timeval_start, timeval_end); | 743 | *res_time = timediff(timeval_start, timeval_end); |
| 791 | 744 | ||
| 792 | if (verbose) | 745 | if (verbose) |
| 793 | printf ("Time elapsed: %f\n", *res_time); | 746 | printf("Time elapsed: %f\n", *res_time); |
| 794 | 747 | ||
| 795 | return status; | 748 | return status; |
| 796 | } | 749 | } |
| 797 | 750 | ||
| 798 | double | 751 | double timediff(struct timeval start, struct timeval end) { |
| 799 | timediff (struct timeval start, struct timeval end) | ||
| 800 | { | ||
| 801 | double diff; | 752 | double diff; |
| 802 | 753 | ||
| 803 | while (start.tv_usec > end.tv_usec) { | 754 | while (start.tv_usec > end.tv_usec) { |
| 804 | --end.tv_sec; | 755 | --end.tv_sec; |
| 805 | end.tv_usec += 1000000; | 756 | end.tv_usec += 1000000; |
| 806 | } | 757 | } |
| 807 | diff = (double)(end.tv_sec - start.tv_sec) | 758 | diff = (double)(end.tv_sec - start.tv_sec) + (double)(end.tv_usec - start.tv_usec) / 1000000.0; |
| 808 | + (double)(end.tv_usec - start.tv_usec) / 1000000.0; | ||
| 809 | return diff; | 759 | return diff; |
| 810 | } | 760 | } |
| 811 | 761 | ||
| 812 | void | 762 | void np_dbi_print_error(dbi_conn conn, char *fmt, ...) { |
| 813 | np_dbi_print_error (dbi_conn conn, char *fmt, ...) | ||
| 814 | { | ||
| 815 | const char *errmsg = NULL; | 763 | const char *errmsg = NULL; |
| 816 | va_list ap; | 764 | va_list ap; |
| 817 | 765 | ||
| 818 | va_start (ap, fmt); | 766 | va_start(ap, fmt); |
| 819 | 767 | ||
| 820 | dbi_conn_error (conn, &errmsg); | 768 | dbi_conn_error(conn, &errmsg); |
| 821 | vprintf (fmt, ap); | 769 | vprintf(fmt, ap); |
| 822 | printf (": %s\n", errmsg); | 770 | printf(": %s\n", errmsg); |
| 823 | 771 | ||
| 824 | va_end (ap); | 772 | va_end(ap); |
| 825 | } | 773 | } |
| 826 | |||
