From b17b2421987bb8a7606948333e75f990b35852b8 Mon Sep 17 00:00:00 2001 From: Ton Voon Date: Wed, 19 Mar 2008 14:42:12 +0000 Subject: 1st pass at check_procs with multiple threshold checks git-svn-id: https://nagiosplug.svn.sourceforge.net/svnroot/nagiosplug/nagiosplug/branches/new_threshold_syntax@1958 f882894a-f735-0410-b71e-b25c423dba1c diff --git a/lib/tests/test_utils.c b/lib/tests/test_utils.c index 278f526..a5189ce 100644 --- a/lib/tests/test_utils.c +++ b/lib/tests/test_utils.c @@ -30,7 +30,7 @@ main (int argc, char **argv) thresholds *thresholds = NULL; int rc; - plan_tests(82); + plan_tests(172); range = parse_range_string("6"); ok( range != NULL, "'6' is valid range"); @@ -40,6 +40,32 @@ main (int argc, char **argv) ok( range->end_infinity == FALSE, "Not using infinity"); free(range); + range = _parse_range_string_v2("6"); + ok( range == NULL, "Missing colon in range" ); + ok( utils_errno == NP_RANGE_MISSING_COLON, "Right error code" ); + + range = _parse_range_string_v2("6:"); + ok( range != NULL, "'6:' is valid range"); + ok( range->start == 6, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end_infinity == TRUE, "Using infinity"); + free(range); + + range = _parse_range_string_v2("6:6"); + ok( range != NULL, "'6:6' is valid range"); + ok( range->start == 6, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end == 6, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + + range = _parse_range_string_v2(":6"); + ok( range != NULL, "':6' is valid range"); + ok( range->start_infinity == TRUE, "Using negative infinity"); + ok( range->end == 6, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("1:12%%"); ok( range != NULL, "'1:12%%' is valid - percentages are ignored"); ok( range->start == 1, "Start correct"); @@ -48,6 +74,14 @@ main (int argc, char **argv) ok( range->end_infinity == FALSE, "Not using infinity"); free(range); + range = _parse_range_string_v2("1:12%%"); + ok( range != NULL, "'1:12%%' is valid - percentages are ignored"); + ok( range->start == 1, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end == 12, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("-7:23"); ok( range != NULL, "'-7:23' is valid range"); ok( range->start == -7, "Start correct"); @@ -56,6 +90,14 @@ main (int argc, char **argv) ok( range->end_infinity == FALSE, "Not using infinity"); free(range); + range = _parse_range_string_v2("-7:23"); + ok( range != NULL, "'-7:23' is valid range"); + ok( range->start == -7, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end == 23, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string(":5.75"); ok( range != NULL, "':5.75' is valid range"); ok( range->start == 0, "Start correct"); @@ -64,6 +106,14 @@ main (int argc, char **argv) ok( range->end_infinity == FALSE, "Not using infinity"); free(range); + range = _parse_range_string_v2(":5.75"); + ok( range != NULL, "':5.75' is valid range"); + ok( range->start == 0, "Start correct"); + ok( range->start_infinity == TRUE, "Using negative infinity"); + ok( range->end == 5.75, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("~:-95.99"); ok( range != NULL, "~:-95.99' is valid range"); ok( range->start_infinity == TRUE, "Using negative infinity"); @@ -71,6 +121,26 @@ main (int argc, char **argv) ok( range->end_infinity == FALSE, "Not using infinity"); free(range); + range = _parse_range_string_v2("~:-95.99"); + ok( range == NULL, "~:-95.99' is invalid range"); + ok( utils_errno == NP_RANGE_UNPARSEABLE, "Correct error code" ); + + /* + * This is currently parseable. This is because ~ is interpreted as a 0 + * and then 95.99 is the end, so we get 0:95.99. Should validate the characters before + * passing to strtod + range = _parse_range_string_v2("~:95.99"); + ok( range == NULL, "~:95.99' is invalid range"); + ok( utils_errno == NP_RANGE_UNPARSEABLE, "Correct error code" ); + */ + + range = _parse_range_string_v2(":-95.99"); + ok( range != NULL, ":-95.99' is valid range"); + ok( range->start_infinity == TRUE, "Using negative infinity"); + ok( range->end == -95.99, "End correct (with rounding errors)"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("12345678901234567890:"); temp = atof("12345678901234567890"); /* Can't just use this because number too large */ ok( range != NULL, "'12345678901234567890:' is valid range"); @@ -83,6 +153,14 @@ main (int argc, char **argv) ok( check_range(temp*2, range) == FALSE, "12345678901234567890*2 - no alert"); free(range); + range = _parse_range_string_v2("12345678901234567890:"); + temp = atof("12345678901234567890"); + ok( range != NULL, "'12345678901234567890:' is valid range"); + ok( range->start == temp, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end_infinity == TRUE, "Using infinity"); + free(range); + range = parse_range_string("~:0"); ok( range != NULL, "'~:0' is valid range"); ok( range->start_infinity == TRUE, "Using negative infinity"); @@ -94,8 +172,16 @@ main (int argc, char **argv) ok( check_range(0, range) == FALSE, "0 - no alert"); free(range); + range = _parse_range_string_v2("-4.33:-4.33"); + ok( range != NULL, "'-4.33:-4.33' is valid range"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->start == -4.33, "Start right"); + ok( range->end == -4.33, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("@0:657.8210567"); - ok( range != 0, "@0:657.8210567' is a valid range"); + ok( range != NULL, "@0:657.8210567' is a valid range"); ok( range->start == 0, "Start correct"); ok( range->start_infinity == FALSE, "Not using negative infinity"); ok( range->end == 657.8210567, "End correct"); @@ -107,6 +193,14 @@ main (int argc, char **argv) ok( check_range(0, range) == TRUE, "0 - alert"); free(range); + range = parse_range_string("^0:657.8210567"); + ok( range != NULL, "^0:657.8210567' is a valid range"); + ok( range->start == 0, "Start correct"); + ok( range->start_infinity == FALSE, "Not using negative infinity"); + ok( range->end == 657.8210567, "End correct"); + ok( range->end_infinity == FALSE, "Not using infinity"); + free(range); + range = parse_range_string("1:1"); ok( range != NULL, "'1:1' is a valid range"); ok( range->start == 1, "Start correct"); @@ -121,22 +215,71 @@ main (int argc, char **argv) range = parse_range_string("2:1"); ok( range == NULL, "'2:1' rejected"); + range = _parse_range_string_v2("2:1"); + ok( range == NULL, "'2:1' rejected"); + ok( utils_errno == NP_RANGE_UNPARSEABLE, "Errno correct" ); + rc = _set_thresholds(&thresholds, NULL, NULL); ok( rc == 0, "Thresholds (NULL, NULL) set"); ok( thresholds->warning == NULL, "Warning not set"); ok( thresholds->critical == NULL, "Critical not set"); + thresholds = _parse_thresholds_string(NULL); + ok( thresholds != NULL, "Threshold still set, even though NULL"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical == NULL, "Critical set to NULL"); + + thresholds = _parse_thresholds_string(""); + ok( thresholds != NULL, "Threshold still set, even though ''"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical == NULL, "Critical set to NULL"); + + thresholds = _parse_thresholds_string("/"); + ok( thresholds != NULL, "Threshold still set, even though '/'"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical == NULL, "Critical set to NULL"); + rc = _set_thresholds(&thresholds, NULL, "80"); ok( rc == 0, "Thresholds (NULL, '80') set"); ok( thresholds->warning == NULL, "Warning not set"); ok( thresholds->critical->end == 80, "Critical set correctly"); + thresholds = _parse_thresholds_string(":80/"); + ok( thresholds != NULL, "Threshold set for ':80/'"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical->start_infinity == TRUE, "Start is right" ); + ok( thresholds->critical->end == 80, "Critical set to 80"); + + thresholds = _parse_thresholds_string(":80"); + ok( thresholds != NULL, "Threshold set for ':80'"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical->start_infinity == TRUE, "Start is right" ); + ok( thresholds->critical->end == 80, "Critical set to 80"); + + thresholds = _parse_thresholds_string("80"); + ok( thresholds == NULL, "Threshold not set because of single value '80'"); + ok( utils_errno == NP_RANGE_MISSING_COLON, "Correct error message"); + rc = _set_thresholds(&thresholds, "5:33", NULL); ok( rc == 0, "Thresholds ('5:33', NULL) set"); ok( thresholds->warning->start == 5, "Warning start set"); ok( thresholds->warning->end == 33, "Warning end set"); ok( thresholds->critical == NULL, "Critical not set"); + thresholds = _parse_thresholds_string("5:33"); + ok( thresholds != NULL, "Threshold set for '5:33'"); + ok( thresholds->warning == NULL, "Warning set to NULL"); + ok( thresholds->critical->start_infinity == FALSE, "Start is right" ); + ok( thresholds->critical->start == 5, "Critical set to 5"); + ok( thresholds->critical->end == 33, "Critical set to 33"); + + thresholds = _parse_thresholds_string("/5:33"); + ok( thresholds != NULL, "Threshold set for '/5:33'"); + ok( thresholds->critical == NULL, "Critical set to NULL"); + ok( thresholds->warning->start_infinity == FALSE, "Start is right" ); + ok( thresholds->warning->start == 5, "Warning start set to 5"); + ok( thresholds->warning->end == 33, "Warning end set to 33"); + rc = _set_thresholds(&thresholds, "30", "60"); ok( rc == 0, "Thresholds ('30', '60') set"); ok( thresholds->warning->end == 30, "Warning set correctly"); @@ -145,6 +288,17 @@ main (int argc, char **argv) ok( get_status(30.0001, thresholds) == STATE_WARNING, "30.0001 - warning"); ok( get_status(69, thresholds) == STATE_CRITICAL, "69 - critical"); + thresholds = _parse_thresholds_string("-6.7:29 / 235.4:3333.33"); + ok( thresholds != NULL, "Threshold set for '-6.7:29 / 235.4:3333.33'"); + ok( thresholds->critical->start_infinity == FALSE, "Critical not starting at infinity"); + ok( thresholds->critical->start == -6.7, "Critical start right" ); + ok( thresholds->critical->end_infinity == FALSE, "Critical not ending at infinity"); + ok( thresholds->critical->end == 29, "Critical end right" ); + ok( thresholds->warning->start_infinity == FALSE, "Start is right" ); + ok( thresholds->warning->start == 235.4, "Warning set to 5"); + ok( thresholds->warning->end_infinity == FALSE, "End is right" ); + ok( thresholds->warning->end == 3333.33, "Warning set to 33"); + char *test; test = np_escaped_string("bob\\n"); ok( strcmp(test, "bob\n") == 0, "bob\\n ok"); diff --git a/lib/utils_base.c b/lib/utils_base.c index d1453c6..1320b71 100644 --- a/lib/utils_base.c +++ b/lib/utils_base.c @@ -98,6 +98,138 @@ range return NULL; } +/* New range string parsing routines, for the v2 thresholds syntax */ +/* Returns range if OK, otherwise errors. Sets utils_errno if error */ +int utils_errno; +range * +_parse_range_string_v2 (char *str) { + range *temp_range; + double start; + double end; + char *end_str; + + temp_range = (range *) malloc(sizeof(range)); + + /* Initialise */ + temp_range->start = 0; + temp_range->start_infinity = FALSE; + temp_range->end = 0; + temp_range->end_infinity = FALSE; + temp_range->alert_on = INSIDE; + + if (str[0] == '^') { + temp_range->alert_on = OUTSIDE; + str++; + } + + end_str = index(str, ':'); + if (end_str == NULL) { + utils_errno = NP_RANGE_MISSING_COLON; + free(temp_range); + temp_range = NULL; + return NULL; + } + end_str++; + if (str[0] == ':') { + temp_range->start_infinity = TRUE; + } else { + start = strtod(str, NULL); /* Will stop at ':' */ + set_range_start(temp_range, start); + } + if (strcmp(end_str, "") != 0) { + end = strtod(end_str, NULL); + set_range_end(temp_range, end); + } else { + temp_range->end_infinity = TRUE; + } + + if (temp_range->start_infinity == TRUE || + temp_range->end_infinity == TRUE || + temp_range->start <= temp_range->end) { + return temp_range; + } + free(temp_range); + temp_range = NULL; + utils_errno = NP_RANGE_UNPARSEABLE; + return NULL; +} + +void +_die_on_parse_error(int errorcode) { + switch (errorcode) { + case NP_RANGE_UNPARSEABLE: + die(STATE_UNKNOWN, _("Range format incorrect\n")); + case NP_WARN_WITHIN_CRIT: + die(STATE_UNKNOWN, _("Warning level is a subset of critical and will not be alerted\n")); + case NP_RANGE_MISSING_COLON: + die(STATE_UNKNOWN, _("Range is missing a colon\n")); + case NP_MEMORY_ERROR: + die(STATE_UNKNOWN, _("Memory error\n")); + } +} + +thresholds +*_parse_thresholds_string(char *string) { + thresholds *temp_thresholds = NULL; + char *separator = NULL; + char *temp_string = NULL; + range *temp_range = NULL; + int rc; + + temp_thresholds = malloc(sizeof(temp_thresholds)); + if (temp_thresholds == NULL) { + utils_errno = NP_MEMORY_ERROR; + return NULL; + } + + temp_thresholds->warning = NULL; + temp_thresholds->critical = NULL; + + if (string == NULL || strcmp(string, "") == 0) + return temp_thresholds; + + if((temp_string = strdup(string)) == NULL) { + free(temp_thresholds); + utils_errno = NP_MEMORY_ERROR; + return NULL; + } + + /* Find critical part and parse the range */ + separator = index(temp_string, '/'); + if (separator) { + *separator = '\0'; + separator++; + } + if ((strcmp(temp_string, "") != 0) && (temp_range = _parse_range_string_v2( temp_string )) == NULL) { + free(temp_thresholds); + free(temp_string); + /* utils_errno already set */ + return NULL; + } + temp_thresholds->critical = temp_range; + + if (separator == NULL || strcmp(separator, "") == 0) { + return temp_thresholds; + } + /* UOM not processed yet */ + if(( temp_range = _parse_range_string_v2( separator )) == NULL) { + free(temp_thresholds); + free(temp_string); + return NULL; + } + temp_thresholds->warning = temp_range; + return temp_thresholds; +} + +thresholds +*parse_thresholds_string(char *string) +{ + thresholds *my_threshold; + if ((my_threshold = _parse_thresholds_string(string)) == NULL) + _die_on_parse_error(utils_errno); + return my_threshold; +} + /* returns 0 if okay, otherwise 1 */ int _set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_string) @@ -139,8 +271,7 @@ set_thresholds(thresholds **my_thresholds, char *warn_string, char *critical_str } } -void print_thresholds(const char *threshold_name, thresholds *my_threshold) { - printf("%s - ", threshold_name); +void print_thresholds(thresholds *my_threshold) { if (! my_threshold) { printf("Threshold not set"); } else { diff --git a/lib/utils_base.h b/lib/utils_base.h index bda7659..c616c5b 100644 --- a/lib/utils_base.h +++ b/lib/utils_base.h @@ -31,7 +31,7 @@ typedef struct thresholds_struct { range *parse_range_string (char *); int _set_thresholds(thresholds **, char *, char *); void set_thresholds(thresholds **, char *, char *); -void print_thresholds(const char *, thresholds *); +void print_thresholds(thresholds *); int check_range(double, range *); int get_status(double, thresholds *); @@ -39,9 +39,22 @@ char *np_escaped_string (const char *); void die (int, const char *, ...) __attribute__((noreturn,format(printf, 2, 3))); -/* Return codes for _set_thresholds */ -#define NP_RANGE_UNPARSEABLE 1 -#define NP_WARN_WITHIN_CRIT 2 + +/* Parses a threshold string, as entered from command line */ +/* Returns a malloc'd threshold* which can be freed */ +thresholds *parse_thresholds_string(char *); +thresholds * _parse_thresholds_string(char *); +void free_thresholds(thresholds *); +range * _parse_range_string_v2(char *); +int utils_errno; + + +/* Error codes */ +#define NP_RANGE_UNPARSEABLE 1 +#define NP_WARN_WITHIN_CRIT 2 +#define NP_RANGE_MISSING_COLON 3 +#define NP_THRESHOLD_UNPARSEABLE 4 +#define NP_MEMORY_ERROR 5 /* a simple check to see if we're running as root. * returns zero on failure, nonzero on success */ diff --git a/plugins/check_cluster.c b/plugins/check_cluster.c index c67573a..3231641 100644 --- a/plugins/check_cluster.c +++ b/plugins/check_cluster.c @@ -80,7 +80,7 @@ int main(int argc, char **argv){ /* Initialize the thresholds */ set_thresholds(&thresholds, warn_threshold, crit_threshold); if(verbose) - print_thresholds("check_cluster", thresholds); + print_thresholds(thresholds); /* check the data values */ for(ptr=strtok(data_vals,",");ptr!=NULL;ptr=strtok(NULL,",")){ diff --git a/plugins/check_procs.c b/plugins/check_procs.c index d56d457..7f3ca21 100644 --- a/plugins/check_procs.c +++ b/plugins/check_procs.c @@ -44,6 +44,7 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "popen.h" #include "utils.h" #include "regex.h" +#include "utils_base.h" #include @@ -53,6 +54,7 @@ int check_thresholds (int); int convert_to_seconds (char *); void print_help (void); void print_usage (void); +void actions_on_failed_state (int, char*); /* Helper routine */ int wmax = -1; int cmax = -1; @@ -74,13 +76,16 @@ int options = 0; /* bitmask of filter criteria to test against */ /* Different metrics */ char *metric_name; enum metric { + NONE, + DEFAULT, METRIC_PROCS, METRIC_VSZ, METRIC_RSS, METRIC_CPU, METRIC_ELAPSED }; -enum metric metric = METRIC_PROCS; +enum metric metric = DEFAULT; +enum metric default_metric = METRIC_PROCS; int verbose = 0; int uid; @@ -99,6 +104,14 @@ char tmp[MAX_INPUT_BUFFER]; FILE *ps_input = NULL; +thresholds *number_threshold = NULL; +thresholds *vsz_threshold = NULL; +thresholds *rss_threshold = NULL; +thresholds *cpu_threshold = NULL; + +int warn = 0; /* number of processes in warn state */ +int crit = 0; /* number of processes in crit state */ +int result = STATE_UNKNOWN; int main (int argc, char **argv) @@ -127,10 +140,14 @@ main (int argc, char **argv) int pos; /* number of spaces before 'args' in `ps` output */ int cols; /* number of columns in ps output */ int expected_cols = PS_COLS - 1; - int warn = 0; /* number of processes in warn state */ - int crit = 0; /* number of processes in crit state */ - int i = 0; - int result = STATE_UNKNOWN; + int i = 0; /* Temporary values */ + double rss_sum = 0; + double vsz_sum = 0; + double cpu_sum = 0; + double vsz_max = 0; + double rss_max = 0; + double cpu_max = 0; + setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); @@ -141,7 +158,6 @@ main (int argc, char **argv) procprog = malloc (MAX_INPUT_BUFFER); asprintf (&metric_name, "PROCS"); - metric = METRIC_PROCS; if (process_arguments (argc, argv) == ERROR) usage4 (_("Could not parse arguments")); @@ -218,6 +234,7 @@ main (int argc, char **argv) /* Ignore self */ if (mypid == procpid) continue; + /* Filter */ if ((options & STAT) && (strstr (statopts, procstat))) resultsum |= STAT; if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL)) @@ -244,35 +261,64 @@ main (int argc, char **argv) continue; procs++; - if (verbose >= 2) { + if (verbose >= 3) { printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", procuid, procvsz, procrss, procpid, procppid, procpcpu, procstat, procetime, procprog, procargs); } - if (metric == METRIC_VSZ) - i = check_thresholds (procvsz); - else if (metric == METRIC_RSS) - i = check_thresholds (procrss); + /* Check against metric - old style single check */ + if (metric == METRIC_VSZ) { + actions_on_failed_state( check_thresholds (procvsz), procprog ); + } else if (metric == METRIC_RSS) { + actions_on_failed_state( check_thresholds (procrss), procprog ); /* TODO? float thresholds for --metric=CPU */ - else if (metric == METRIC_CPU) - i = check_thresholds ((int)procpcpu); - else if (metric == METRIC_ELAPSED) - i = check_thresholds (procseconds); - - if (metric != METRIC_PROCS) { - if (i == STATE_WARNING) { - warn++; - asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog); - result = max_state (result, i); + } else if (metric == METRIC_CPU) { + actions_on_failed_state( check_thresholds ((int)procpcpu), procprog ); + } else if (metric == METRIC_ELAPSED) { + actions_on_failed_state( check_thresholds (procseconds), procprog ); + } + + /* Check against all new style thresholds */ + if (vsz_threshold != NULL) { + if ((i = get_status( procvsz, vsz_threshold )) != STATE_OK ) { + actions_on_failed_state(i, procprog); + if (verbose >= 2) { + printf("VSZ state %d: proc=%s vsz=%d ", i, procprog, procvsz); + print_thresholds( vsz_threshold ); + } + } + } + if (rss_threshold != NULL) { + if ((i = get_status( procrss, rss_threshold )) != STATE_OK ) { + actions_on_failed_state(i, procprog); + if (verbose >= 2) { + printf("RSS: proc=%s rss=%d ", procprog, procrss); + print_thresholds( rss_threshold ); + } } - if (i == STATE_CRITICAL) { - crit++; - asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog); - result = max_state (result, i); + } + if (cpu_threshold != NULL) { + if (( i = get_status( procpcpu, cpu_threshold )) != STATE_OK ) { + actions_on_failed_state(i, procprog); + if (verbose >= 2) { + printf("CPU: proc=%s cpu=%f ", procprog, procpcpu); + print_thresholds( cpu_threshold ); + } } } + + /* Summary information */ + rss_sum += procrss; + vsz_sum += procvsz; + cpu_sum += procpcpu; + if (procrss > rss_max) + rss_max = procrss; + if (procvsz > vsz_max) + vsz_max = procvsz; + if (procpcpu > cpu_max) + cpu_max = procpcpu; } /* This should not happen */ else if (verbose) { @@ -308,7 +354,12 @@ main (int argc, char **argv) /* Needed if procs found, but none match filter */ if ( metric == METRIC_PROCS ) { - result = max_state (result, check_thresholds (procs) ); + result = max_state (result, i = check_thresholds (procs) ); + } + + if (number_threshold != NULL) { + i = get_status( procs, number_threshold ); + actions_on_failed_state(i, "NUMBER_OF_PROCESSES"); } if ( result == STATE_OK ) { @@ -316,12 +367,12 @@ main (int argc, char **argv) } else if (result == STATE_WARNING) { printf ("%s %s: ", metric_name, _("WARNING")); if ( metric != METRIC_PROCS ) { - printf (_("%d warn out of "), warn); + printf (_("Alerts: %d warn from "), warn); } } else if (result == STATE_CRITICAL) { printf ("%s %s: ", metric_name, _("CRITICAL")); if (metric != METRIC_PROCS) { - printf (_("%d crit, %d warn out of "), crit, warn); + printf (_("Alerts: %d crit, %d warn from "), crit, warn); } } printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs); @@ -333,6 +384,17 @@ main (int argc, char **argv) if ( verbose >= 1 && strcmp(fails,"") ) printf (" [%s]", fails); + printf(" | "); + if( number_threshold != NULL) + printf("number=%d ", procs); + if (procs > 0) { + if( vsz_threshold != NULL) + printf("vsz=%.0f ", vsz_sum/procs); + if( rss_threshold != NULL) + printf("rss=%.0f ", rss_sum/procs); + if( cpu_threshold != NULL) + printf("cpu=%.2f ", cpu_sum/procs); + } printf ("\n"); return result; } @@ -368,6 +430,22 @@ process_arguments (int argc, char **argv) {"verbose", no_argument, 0, 'v'}, {"ereg-argument-array", required_argument, 0, CHAR_MAX+1}, {"input-file", required_argument, 0, CHAR_MAX+2}, + {"number", optional_argument, 0, CHAR_MAX+3}, + {"rss-threshold", optional_argument, 0, CHAR_MAX+4}, + /* + {"rss-max", optional_argument, 0, CHAR_MAX+5}, + {"rss-sum", optional_argument, 0, CHAR_MAX+6}, + */ + {"vsz-threshold", optional_argument, 0, CHAR_MAX+7}, + /* + {"vsz-max", optional_argument, 0, CHAR_MAX+8}, + {"vsz-sum", optional_argument, 0, CHAR_MAX+9}, + */ + {"cpu-threshold", optional_argument, 0, CHAR_MAX+10}, + /* + {"cpu-max", optional_argument, 0, CHAR_MAX+11}, + {"cpu-sum", optional_argument, 0, CHAR_MAX+12}, + */ {0, 0, 0, 0} }; @@ -537,6 +615,26 @@ process_arguments (int argc, char **argv) case CHAR_MAX+2: input_filename = optarg; break; + case CHAR_MAX+3: + number_threshold = parse_thresholds_string(optarg); + if (metric == DEFAULT) + default_metric=NONE; + break; + case CHAR_MAX+4: + rss_threshold = parse_thresholds_string(optarg); + if (metric == DEFAULT) + default_metric=NONE; + break; + case CHAR_MAX+7: + vsz_threshold = parse_thresholds_string(optarg); + if (metric == DEFAULT) + default_metric=NONE; + break; + case CHAR_MAX+10: + cpu_threshold = parse_thresholds_string(optarg); + if (metric == DEFAULT) + default_metric=NONE; + break; } } @@ -598,6 +696,9 @@ validate_arguments () if (fails==NULL) fails = strdup(""); + if (metric==DEFAULT) + metric = default_metric; + return options; } @@ -636,6 +737,21 @@ check_thresholds (int value) } +void +actions_on_failed_state(int state, char *procprog) { + result = max_state (result, state); + if (state != STATE_WARNING && state != STATE_CRITICAL) + return; + if (state == STATE_WARNING) { + warn++; + } + if (state == STATE_CRITICAL) { + crit++; + } + /* TODO: This should be a hash, to remove duplicates */ + asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog); +} + /* convert the elapsed time to seconds */ int convert_to_seconds(char *etime) { @@ -707,31 +823,21 @@ print_help (void) printf ("Copyright (c) 1999 Ethan Galstad \n"); printf (COPYRIGHT, copyright, email); - printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified")); - printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number")); - printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check.")); + print_usage (); printf ("\n\n"); - - print_usage (); - printf ("%s\n", _("Required Arguments:")); - printf (" %s\n", "-w, --warning=RANGE"); - printf (" %s\n", _("Generate warning state if metric is outside this range")); - printf (" %s\n", "-c, --critical=RANGE"); - printf (" %s\n", _("Generate critical state if metric is outside this range")); + printf("Checks all processes and, optionally, filters to a subset to check thresholds values against.\n"); + printf("Can specify any of the following thresholds:\n"); + + printf(" --number=THRESHOLD - Compares the number of matching processes\n"); + printf(" --vsz-threshold=THRESHOLD - Compares each process' vsz (in kilobytes)\n"); + printf(" --rss-threshold=THRESHOLD - Compares each process' rss (in kilobytes)\n"); + printf(" --cpu-threshold=THRESHOLD - Compares each process' cpu (in %%)\n"); + /* TODO: Add support for etime */ + printf("\n\n"); printf ("%s\n", _("Optional Arguments:")); - printf (" %s\n", "-m, --metric=TYPE"); - printf (" %s\n", _("Check thresholds against metric. Valid types:")); - printf (" %s\n", _("PROCS - number of processes (default)")); - printf (" %s\n", _("VSZ - virtual memory size")); - printf (" %s\n", _("RSS - resident set memory size")); - printf (" %s\n", _("CPU - percentage cpu")); -/* only linux etime is support currently */ -#if defined( __linux__ ) - printf (" %s\n", _("ELAPSED - time elapsed in seconds")); -#endif /* defined(__linux__) */ printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT); printf (" %s\n", "-v, --verbose"); @@ -759,29 +865,25 @@ print_help (void) printf (" %s\n", "-C, --command=COMMAND"); printf (" %s\n", _("Only scan for exact matches of COMMAND (without path).")); - printf(_("\n\ -RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\ -specified 'max:min', a warning status will be generated if the\n\ -count is inside the specified range\n\n")); + printf("\n"); - printf(_("\ -This plugin checks the number of currently running processes and\n\ -generates WARNING or CRITICAL states if the process count is outside\n\ -the specified threshold ranges. The process count can be filtered by\n\ -process owner, parent process PID, current state (e.g., 'Z'), or may\n\ -be the total number of running processes\n\n")); + printf("\ +THRESHOLDS are specified as 'critical_range/warning_range' where\n\ +RANGES are defined as 'min:max'. max can be removed if it is infinity.\n\ +Alerts will occur inside this range, unless you specify '^' before\n\ +the range, to mean alert outside this range\n\n"); printf ("%s\n", _("Examples:")); - printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry"); - printf (" %s\n", _("Warning if not two processes with command name portsentry.")); - printf (" %s\n\n", _("Critical if < 2 or > 1024 processes")); - printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root"); - printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing")); - printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root")); - printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ"); - printf (" %s\n\n", _("Alert if vsz of any processes over 50K or 100K")); - printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU"); - printf (" %s\n\n", _("Alert if cpu of any processes over 10%% or 20%%")); + printf (" %s\n", "check_procs --number=:2/5: -C portsentry"); + printf (" %s\n", _("Warning if greater than five processes with command name portsentry.")); + printf (" %s\n\n", _("Critical if <= 2 processes")); + printf (" %s\n", "check_procs --vsz-threshold=100:/50:"); + printf (" %s\n\n", _("Warning if vsz of any processes is over 50K or critical if vsz is over 100K")); + printf (" %s\n", "check_procs --cpu-threshold=20:/10: --ereg-argument-array='java.*server'"); + printf (" %s\n\n", _("For all processes with arguments matching the regular expression, warning if cpu is over 10% or critical if over 20%")); + printf (" %s\n", "check_procs --rss-threshold=100: --number=/:10 --cpu-threshold=30:/10: -a '/usr/local/bin/perl' -u root"); + printf (" %s\n", _("Critical if rss >= 100K, or warning if total number of process <= 10, or critical if cpu >= 30% or warning if cpu >= 10%.")); + printf (" %s\n", _("Filter by arguments containing '/usr/local/bin/perl' and owned by root")); printf (_(UT_SUPPORT)); } -- cgit v0.10-9-g596f