diff options
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | plugins/check_http.c | 24 | ||||
-rw-r--r-- | plugins/check_mysql.c | 76 | ||||
-rw-r--r-- | plugins/check_snmp.c | 41 | ||||
-rwxr-xr-x | plugins/tests/check_http.t | 13 |
5 files changed, 134 insertions, 23 deletions
@@ -14,6 +14,7 @@ This file documents the major additions and syntax changes between releases. Add --without-{dbi,ldap,radius} options to ./configure Made Verbose output of check_sensors compliant (Gabriele Tozzi) New switch -E/--extended-perfdata for check_http to print additional performance data (Sebastian Nohn) + New check_http -d option to specify a string to expect within the response headers Add support for executing queries to check_pgsql Let check_pgsql accept a UNIX socket directory as hostname New check_pgsql -o option to specify additional connection parameters @@ -23,6 +24,8 @@ This file documents the major additions and syntax changes between releases. New check_procs -k option to ignore kernel threads (on Linux) Let check_procs use /proc/<PID>/exe (if available) instead of getpid(2), unless -T is specified Let check_mysql support SSL + Let check_mysql add perfromance metrics for all checks + New check_snmp --offset option to allow for adding/substracting an offset value to sensor data FIXES Change the MAIL FROM command generated by check_smtp to be RFC compliant diff --git a/plugins/check_http.c b/plugins/check_http.c index 6db38e8c..ea7a6736 100644 --- a/plugins/check_http.c +++ b/plugins/check_http.c @@ -100,7 +100,9 @@ char *user_agent; int server_url_length; int server_expect_yn = 0; char server_expect[MAX_INPUT_BUFFER] = HTTP_EXPECT; +char header_expect[MAX_INPUT_BUFFER] = ""; char string_expect[MAX_INPUT_BUFFER] = ""; +char output_header_search[30] = ""; char output_string_search[30] = ""; char *warning_thresholds = NULL; char *critical_thresholds = NULL; @@ -205,6 +207,7 @@ process_arguments (int argc, char **argv) {"port", required_argument, 0, 'p'}, {"authorization", required_argument, 0, 'a'}, {"proxy_authorization", required_argument, 0, 'b'}, + {"header-string", required_argument, 0, 'd'}, {"string", required_argument, 0, 's'}, {"expect", required_argument, 0, 'e'}, {"regex", required_argument, 0, 'r'}, @@ -243,7 +246,7 @@ process_arguments (int argc, char **argv) } while (1) { - c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:e:p:s:R:r:u:f:C:nlLS::m:M:N:E", longopts, &option); + c = getopt_long (argc, argv, "Vvh46t:c:w:A:k:H:P:j:T:I:a:b:d:e:p:s:R:r:u:f:C:nlLS::m:M:N:E", longopts, &option); if (c == -1 || c == EOF) break; @@ -392,6 +395,10 @@ process_arguments (int argc, char **argv) free(http_method); http_method = strdup (optarg); break; + case 'd': /* string or substring */ + strncpy (header_expect, optarg, MAX_INPUT_BUFFER - 1); + header_expect[MAX_INPUT_BUFFER - 1] = 0; + break; case 's': /* string or substring */ strncpy (string_expect, optarg, MAX_INPUT_BUFFER - 1); string_expect[MAX_INPUT_BUFFER - 1] = 0; @@ -1085,6 +1092,17 @@ check_http (void) } /* Page and Header content checks go here */ + if (strlen (header_expect)) { + if (!strstr (header, header_expect)) { + strncpy(&output_header_search[0],header_expect,sizeof(output_header_search)); + if(output_header_search[sizeof(output_header_search)-1]!='\0') { + bcopy("...",&output_header_search[sizeof(output_header_search)-4],4); + } + xasprintf (&msg, _("%sheader '%s' not found on '%s://%s:%d%s', "), msg, output_header_search, use_ssl ? "https" : "http", host_name ? host_name : server_address, server_port, server_url); + result = STATE_CRITICAL; + } + } + if (strlen (string_expect)) { if (!strstr (page, string_expect)) { @@ -1434,6 +1452,8 @@ print_help (void) printf (" %s", _("the first (status) line of the server response (default: ")); printf ("%s)\n", HTTP_EXPECT); printf (" %s\n", _("If specified skips all other status line logic (ex: 3xx, 4xx, 5xx processing)")); + printf (" %s\n", "-d, --header-string=STRING"); + printf (" %s\n", _("String to expect in the response headers")); printf (" %s\n", "-s, --string=STRING"); printf (" %s\n", _("String to expect in the content")); printf (" %s\n", "-u, --url=PATH"); @@ -1535,7 +1555,7 @@ print_usage (void) printf (" %s -H <vhost> | -I <IP-address> [-u <uri>] [-p <port>]\n",progname); printf (" [-w <warn time>] [-c <critical time>] [-t <timeout>] [-L] [-a auth]\n"); printf (" [-b proxy_auth] [-f <ok|warning|critcal|follow|sticky|stickyport>]\n"); - printf (" [-e <expect>] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); + printf (" [-e <expect>] [-d string] [-s string] [-l] [-r <regex> | -R <case-insensitive regex>]\n"); printf (" [-P string] [-m <min_pg_size>:<max_pg_size>] [-4|-6] [-N] [-M <age>]\n"); printf (" [-A string] [-k string] [-S <version>] [--sni] [-C <warn_age>[,<crit_age>]]\n"); printf (" [-T <content-type>] [-j method]\n"); diff --git a/plugins/check_mysql.c b/plugins/check_mysql.c index ad3d86f3..11d4a2fd 100644 --- a/plugins/check_mysql.c +++ b/plugins/check_mysql.c @@ -59,6 +59,32 @@ unsigned int db_port = MYSQL_PORT; int check_slave = 0, warn_sec = 0, crit_sec = 0; int verbose = 0; +static double warning_time = 0; +static double critical_time = 0; + +#define LENGTH_METRIC_UNIT 6 +static const char *metric_unit[LENGTH_METRIC_UNIT] = { + "Open_files", + "Open_tables", + "Qcache_free_memory", + "Qcache_queries_in_cache", + "Threads_connected", + "Threads_running" +}; + +#define LENGTH_METRIC_COUNTER 9 +static const char *metric_counter[LENGTH_METRIC_COUNTER] = { + "Connections", + "Qcache_hits", + "Qcache_inserts", + "Qcache_lowmem_prunes", + "Qcache_not_cached", + "Queries", + "Questions", + "Table_locks_waited", + "Uptime" +}; + thresholds *my_threshold = NULL; int process_arguments (int, char **); @@ -79,6 +105,9 @@ main (int argc, char **argv) char *result = NULL; char *error = NULL; char slaveresult[SLAVERESULTSIZE]; + char* perf; + + perf = strdup (""); setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -126,6 +155,37 @@ main (int argc, char **argv) die (STATE_CRITICAL, "%s\n", mysql_error (&mysql)); } + /* try to fetch some perf data */ + if (mysql_query (&mysql, "show global status") == 0) { + if ( (res = mysql_store_result (&mysql)) == NULL) { + error = strdup(mysql_error(&mysql)); + mysql_close (&mysql); + die (STATE_CRITICAL, _("status store_result error: %s\n"), error); + } + + while ( (row = mysql_fetch_row (res)) != NULL) { + int i; + + for(i = 0; i < LENGTH_METRIC_UNIT; i++) { + if (strcmp(row[0], metric_unit[i]) == 0) { + xasprintf(&perf, "%s%s ", perf, perfdata(metric_unit[i], + atol(row[1]), "", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0)); + continue; + } + } + for(i = 0; i < LENGTH_METRIC_COUNTER; i++) { + if (strcmp(row[0], metric_counter[i]) == 0) { + xasprintf(&perf, "%s%s ", perf, perfdata(metric_counter[i], + atol(row[1]), "c", FALSE, 0, FALSE, 0, FALSE, 0, FALSE, 0)); + continue; + } + } + } + /* remove trailing space */ + if (strlen(perf) > 0) + perf[strlen(perf) - 1] = '\0'; + } + if(check_slave) { /* check the slave status */ if (mysql_query (&mysql, "show slave status") != 0) { @@ -218,11 +278,17 @@ main (int argc, char **argv) status = get_status(value, my_threshold); + xasprintf (&perf, "%s %s", perf, fperfdata ("seconds behind master", value, "s", + TRUE, (double) warning_time, + TRUE, (double) critical_time, + FALSE, 0, + FALSE, 0)); + if (status == STATE_WARNING) { - printf("SLOW_SLAVE %s: %s\n", _("WARNING"), slaveresult); + printf("SLOW_SLAVE %s: %s|%s\n", _("WARNING"), slaveresult, perf); exit(STATE_WARNING); } else if (status == STATE_CRITICAL) { - printf("SLOW_SLAVE %s: %s\n", _("CRITICAL"), slaveresult); + printf("SLOW_SLAVE %s: %s|%s\n", _("CRITICAL"), slaveresult, perf); exit(STATE_CRITICAL); } } @@ -237,9 +303,9 @@ main (int argc, char **argv) /* print out the result of stats */ if (check_slave) { - printf ("%s %s\n", result, slaveresult); + printf ("%s %s|%s\n", result, slaveresult, perf); } else { - printf ("%s\n", result); + printf ("%s|%s\n", result, perf); } return STATE_OK; @@ -339,9 +405,11 @@ process_arguments (int argc, char **argv) break; case 'w': warning = optarg; + warning_time = strtod (warning, NULL); break; case 'c': critical = optarg; + critical_time = strtod (critical, NULL); break; case 'V': /* version */ print_revision (progname, NP_VERSION); diff --git a/plugins/check_snmp.c b/plugins/check_snmp.c index 7c5d0ec5..7c3bc4b9 100644 --- a/plugins/check_snmp.c +++ b/plugins/check_snmp.c @@ -63,6 +63,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #define L_CALCULATE_RATE CHAR_MAX+1 #define L_RATE_MULTIPLIER CHAR_MAX+2 #define L_INVERT_SEARCH CHAR_MAX+3 +#define L_OFFSET CHAR_MAX+4 /* Gobble to string - stop incrementing c when c[0] match one of the * characters in s */ @@ -138,6 +139,7 @@ char *output_delim; char *miblist = NULL; int needmibs = FALSE; int calculate_rate = 0; +double offset = 0.0; int rate_multiplier = 1; state_data *previous_state; double previous_value[MAX_OIDS]; @@ -274,35 +276,36 @@ main (int argc, char **argv) snmpcmd = strdup (PATH_TO_SNMPGET); } - /* 9 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */ - command_line = calloc (9 + numauthpriv + 1 + numoids + 1, sizeof (char *)); + /* 10 arguments to pass before authpriv options + 1 for host and numoids. Add one for terminating NULL */ + command_line = calloc (10 + numauthpriv + 1 + numoids + 1, sizeof (char *)); command_line[0] = snmpcmd; - command_line[1] = strdup ("-t"); - xasprintf (&command_line[2], "%d", timeout_interval); - command_line[3] = strdup ("-r"); - xasprintf (&command_line[4], "%d", retries); - command_line[5] = strdup ("-m"); - command_line[6] = strdup (miblist); - command_line[7] = "-v"; - command_line[8] = strdup (proto); + command_line[1] = strdup ("-Le"); + command_line[2] = strdup ("-t"); + xasprintf (&command_line[3], "%d", timeout_interval); + command_line[4] = strdup ("-r"); + xasprintf (&command_line[5], "%d", retries); + command_line[6] = strdup ("-m"); + command_line[7] = strdup (miblist); + command_line[8] = "-v"; + command_line[9] = strdup (proto); for (i = 0; i < numauthpriv; i++) { - command_line[9 + i] = authpriv[i]; + command_line[10 + i] = authpriv[i]; } - xasprintf (&command_line[9 + numauthpriv], "%s:%s", server_address, port); + xasprintf (&command_line[10 + numauthpriv], "%s:%s", server_address, port); /* This is just for display purposes, so it can remain a string */ - xasprintf(&cl_hidden_auth, "%s -t %d -r %d -m %s -v %s %s %s:%s", + xasprintf(&cl_hidden_auth, "%s -Le -t %d -r %d -m %s -v %s %s %s:%s", snmpcmd, timeout_interval, retries, strlen(miblist) ? miblist : "''", proto, "[authpriv]", server_address, port); for (i = 0; i < numoids; i++) { - command_line[9 + numauthpriv + 1 + i] = oids[i]; + command_line[10 + numauthpriv + 1 + i] = oids[i]; xasprintf(&cl_hidden_auth, "%s %s", cl_hidden_auth, oids[i]); } - command_line[9 + numauthpriv + 1 + numoids] = NULL; + command_line[10 + numauthpriv + 1 + numoids] = NULL; if (verbose) printf ("%s\n", cl_hidden_auth); @@ -429,7 +432,7 @@ main (int argc, char **argv) ptr = strpbrk (show, "0123456789"); if (ptr == NULL) die (STATE_UNKNOWN,_("No valid data returned (%s)\n"), show); - response_value[i] = strtod (ptr, NULL); + response_value[i] = strtod (ptr, NULL) + offset; if(calculate_rate) { if (previous_state!=NULL) { @@ -618,6 +621,7 @@ process_arguments (int argc, char **argv) {"next", no_argument, 0, 'n'}, {"rate", no_argument, 0, L_CALCULATE_RATE}, {"rate-multiplier", required_argument, 0, L_RATE_MULTIPLIER}, + {"offset", required_argument, 0, L_OFFSET}, {"invert-search", no_argument, 0, L_INVERT_SEARCH}, {"perf-oids", no_argument, 0, 'O'}, {0, 0, 0, 0} @@ -832,6 +836,9 @@ process_arguments (int argc, char **argv) if(!is_integer(optarg)||((rate_multiplier=atoi(optarg))<=0)) usage2(_("Rate multiplier must be a positive integer"),optarg); break; + case L_OFFSET: + offset=strtod(optarg,NULL); + break; case L_INVERT_SEARCH: invert_search=1; break; @@ -1080,6 +1087,8 @@ print_help (void) printf (" %s\n", _("Enable rate calculation. See 'Rate Calculation' below")); printf (" %s\n", "--rate-multiplier"); printf (" %s\n", _("Converts rate per second. For example, set to 60 to convert to per minute")); + printf (" %s\n", "--offset=OFFSET"); + printf (" %s\n", _("Add/substract the specified OFFSET to numeric sensor data")); /* Tests Against Strings */ printf (" %s\n", "-s, --string=STRING"); diff --git a/plugins/tests/check_http.t b/plugins/tests/check_http.t index 9f97abdc..c3085e13 100755 --- a/plugins/tests/check_http.t +++ b/plugins/tests/check_http.t @@ -17,7 +17,7 @@ use Test::More; use NPTest; use FindBin qw($Bin); -my $common_tests = 66; +my $common_tests = 70; my $ssl_only_tests = 8; # Check that all dependent modules are available eval { @@ -151,6 +151,10 @@ sub run_server { unshift @persist, $c; delete($persist[1000]); next MAINLOOP; + } elsif ($r->url->path eq "/header_check") { + $c->send_basic_header; + $c->send_header('foo'); + $c->send_crlf; } else { $c->send_error(HTTP::Status->RC_FORBIDDEN); } @@ -223,6 +227,13 @@ sub run_common_tests { is( $result->return_code, 2, "Missing string check"); like( $result->output, qr%HTTP CRITICAL: HTTP/1\.1 200 OK - string 'NonRootWithOver30charsAndM...' not found on 'https?://127\.0\.0\.1:\d+/file/root'%, "Shows search string and location"); + $result = NPTest->testCmd( "$command -u /header_check -d foo" ); + is( $result->return_code, 0, "header_check search for string"); + like( $result->output, '/^HTTP OK: HTTP/1.1 200 OK - 96 bytes in [\d\.]+ second/', "Output correct" ); + + $result = NPTest->testCmd( "$command -u /header_check -d bar" ); + is( $result->return_code, 2, "Missing header string check"); + like( $result->output, qr%^HTTP CRITICAL: HTTP/1\.1 200 OK - header 'bar' not found on 'https?://127\.0\.0\.1:\d+/header_check'%, "Shows search string and location"); my $cmd; $cmd = "$command -u /slow"; |