diff options
Diffstat (limited to 'plugins/check_procs.c')
| -rw-r--r-- | plugins/check_procs.c | 190 |
1 files changed, 97 insertions, 93 deletions
diff --git a/plugins/check_procs.c b/plugins/check_procs.c index 2f2dcc58..d09bd8b6 100644 --- a/plugins/check_procs.c +++ b/plugins/check_procs.c | |||
| @@ -42,18 +42,21 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; | |||
| 42 | #include "regex.h" | 42 | #include "regex.h" |
| 43 | 43 | ||
| 44 | #include <pwd.h> | 44 | #include <pwd.h> |
| 45 | #include <errno.h> | ||
| 46 | |||
| 47 | #ifdef HAVE_SYS_STAT_H | ||
| 48 | #include <sys/stat.h> | ||
| 49 | #endif | ||
| 45 | 50 | ||
| 46 | int process_arguments (int, char **); | 51 | int process_arguments (int, char **); |
| 47 | int validate_arguments (void); | 52 | int validate_arguments (void); |
| 48 | int check_thresholds (int); | ||
| 49 | int convert_to_seconds (char *); | 53 | int convert_to_seconds (char *); |
| 50 | void print_help (void); | 54 | void print_help (void); |
| 51 | void print_usage (void); | 55 | void print_usage (void); |
| 52 | 56 | ||
| 53 | int wmax = -1; | 57 | char *warning_range = NULL; |
| 54 | int cmax = -1; | 58 | char *critical_range = NULL; |
| 55 | int wmin = -1; | 59 | thresholds *procs_thresholds = NULL; |
| 56 | int cmin = -1; | ||
| 57 | 60 | ||
| 58 | int options = 0; /* bitmask of filter criteria to test against */ | 61 | int options = 0; /* bitmask of filter criteria to test against */ |
| 59 | #define ALL 1 | 62 | #define ALL 1 |
| @@ -67,6 +70,10 @@ int options = 0; /* bitmask of filter criteria to test against */ | |||
| 67 | #define PCPU 256 | 70 | #define PCPU 256 |
| 68 | #define ELAPSED 512 | 71 | #define ELAPSED 512 |
| 69 | #define EREG_ARGS 1024 | 72 | #define EREG_ARGS 1024 |
| 73 | |||
| 74 | #define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads: | ||
| 75 | ppid of procs are compared to pid of this proc*/ | ||
| 76 | |||
| 70 | /* Different metrics */ | 77 | /* Different metrics */ |
| 71 | char *metric_name; | 78 | char *metric_name; |
| 72 | enum metric { | 79 | enum metric { |
| @@ -92,9 +99,21 @@ regex_t re_args; | |||
| 92 | char *fmt; | 99 | char *fmt; |
| 93 | char *fails; | 100 | char *fails; |
| 94 | char tmp[MAX_INPUT_BUFFER]; | 101 | char tmp[MAX_INPUT_BUFFER]; |
| 102 | int kthread_filter = 0; | ||
| 103 | int usepid = 0; /* whether to test for pid or /proc/pid/exe */ | ||
| 95 | 104 | ||
| 96 | FILE *ps_input = NULL; | 105 | FILE *ps_input = NULL; |
| 97 | 106 | ||
| 107 | static int | ||
| 108 | stat_exe (const pid_t pid, struct stat *buf) { | ||
| 109 | char *path; | ||
| 110 | int ret; | ||
| 111 | xasprintf(&path, "/proc/%d/exe", pid); | ||
| 112 | ret = stat(path, buf); | ||
| 113 | free(path); | ||
| 114 | return ret; | ||
| 115 | } | ||
| 116 | |||
| 98 | 117 | ||
| 99 | int | 118 | int |
| 100 | main (int argc, char **argv) | 119 | main (int argc, char **argv) |
| @@ -104,9 +123,13 @@ main (int argc, char **argv) | |||
| 104 | char *procprog; | 123 | char *procprog; |
| 105 | 124 | ||
| 106 | pid_t mypid = 0; | 125 | pid_t mypid = 0; |
| 126 | struct stat statbuf; | ||
| 127 | dev_t mydev = 0; | ||
| 128 | ino_t myino = 0; | ||
| 107 | int procuid = 0; | 129 | int procuid = 0; |
| 108 | pid_t procpid = 0; | 130 | pid_t procpid = 0; |
| 109 | pid_t procppid = 0; | 131 | pid_t procppid = 0; |
| 132 | pid_t kthread_ppid = 0; | ||
| 110 | int procvsz = 0; | 133 | int procvsz = 0; |
| 111 | int procrss = 0; | 134 | int procrss = 0; |
| 112 | int procseconds = 0; | 135 | int procseconds = 0; |
| @@ -127,6 +150,7 @@ main (int argc, char **argv) | |||
| 127 | int crit = 0; /* number of processes in crit state */ | 150 | int crit = 0; /* number of processes in crit state */ |
| 128 | int i = 0, j = 0; | 151 | int i = 0, j = 0; |
| 129 | int result = STATE_UNKNOWN; | 152 | int result = STATE_UNKNOWN; |
| 153 | int ret; | ||
| 130 | output chld_out, chld_err; | 154 | output chld_out, chld_err; |
| 131 | 155 | ||
| 132 | setlocale (LC_ALL, ""); | 156 | setlocale (LC_ALL, ""); |
| @@ -146,8 +170,16 @@ main (int argc, char **argv) | |||
| 146 | if (process_arguments (argc, argv) == ERROR) | 170 | if (process_arguments (argc, argv) == ERROR) |
| 147 | usage4 (_("Could not parse arguments")); | 171 | usage4 (_("Could not parse arguments")); |
| 148 | 172 | ||
| 149 | /* get our pid */ | 173 | /* find ourself */ |
| 150 | mypid = getpid(); | 174 | mypid = getpid(); |
| 175 | if (usepid || stat_exe(mypid, &statbuf) == -1) { | ||
| 176 | /* usepid might have been set by -T */ | ||
| 177 | usepid = 1; | ||
| 178 | } else { | ||
| 179 | usepid = 0; | ||
| 180 | mydev = statbuf.st_dev; | ||
| 181 | myino = statbuf.st_ino; | ||
| 182 | } | ||
| 151 | 183 | ||
| 152 | /* Set signal handling and alarm timeout */ | 184 | /* Set signal handling and alarm timeout */ |
| 153 | if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { | 185 | if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) { |
| @@ -202,7 +234,28 @@ main (int argc, char **argv) | |||
| 202 | procetime, procprog, procargs); | 234 | procetime, procprog, procargs); |
| 203 | 235 | ||
| 204 | /* Ignore self */ | 236 | /* Ignore self */ |
| 205 | if (mypid == procpid) continue; | 237 | if ((usepid && mypid == procpid) || |
| 238 | (!usepid && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino) || | ||
| 239 | (ret == -1 && errno == ENOENT))) { | ||
| 240 | if (verbose >= 3) | ||
| 241 | printf("not considering - is myself or gone\n"); | ||
| 242 | continue; | ||
| 243 | } | ||
| 244 | |||
| 245 | /* filter kernel threads (childs of KTHREAD_PARENT)*/ | ||
| 246 | /* TODO adapt for other OSes than GNU/Linux | ||
| 247 | sorry for not doing that, but I've no other OSes to test :-( */ | ||
| 248 | if (kthread_filter == 1) { | ||
| 249 | /* get pid KTHREAD_PARENT */ | ||
| 250 | if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT) ) | ||
| 251 | kthread_ppid = procpid; | ||
| 252 | |||
| 253 | if (kthread_ppid == procppid) { | ||
| 254 | if (verbose >= 2) | ||
| 255 | printf ("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs); | ||
| 256 | continue; | ||
| 257 | } | ||
| 258 | } | ||
| 206 | 259 | ||
| 207 | if ((options & STAT) && (strstr (statopts, procstat))) | 260 | if ((options & STAT) && (strstr (statopts, procstat))) |
| 208 | resultsum |= STAT; | 261 | resultsum |= STAT; |
| @@ -238,14 +291,14 @@ main (int argc, char **argv) | |||
| 238 | } | 291 | } |
| 239 | 292 | ||
| 240 | if (metric == METRIC_VSZ) | 293 | if (metric == METRIC_VSZ) |
| 241 | i = check_thresholds (procvsz); | 294 | i = get_status ((double)procvsz, procs_thresholds); |
| 242 | else if (metric == METRIC_RSS) | 295 | else if (metric == METRIC_RSS) |
| 243 | i = check_thresholds (procrss); | 296 | i = get_status ((double)procrss, procs_thresholds); |
| 244 | /* TODO? float thresholds for --metric=CPU */ | 297 | /* TODO? float thresholds for --metric=CPU */ |
| 245 | else if (metric == METRIC_CPU) | 298 | else if (metric == METRIC_CPU) |
| 246 | i = check_thresholds ((int)procpcpu); | 299 | i = get_status (procpcpu, procs_thresholds); |
| 247 | else if (metric == METRIC_ELAPSED) | 300 | else if (metric == METRIC_ELAPSED) |
| 248 | i = check_thresholds (procseconds); | 301 | i = get_status ((double)procseconds, procs_thresholds); |
| 249 | 302 | ||
| 250 | if (metric != METRIC_PROCS) { | 303 | if (metric != METRIC_PROCS) { |
| 251 | if (i == STATE_WARNING) { | 304 | if (i == STATE_WARNING) { |
| @@ -276,7 +329,7 @@ main (int argc, char **argv) | |||
| 276 | 329 | ||
| 277 | /* Needed if procs found, but none match filter */ | 330 | /* Needed if procs found, but none match filter */ |
| 278 | if ( metric == METRIC_PROCS ) { | 331 | if ( metric == METRIC_PROCS ) { |
| 279 | result = max_state (result, check_thresholds (procs) ); | 332 | result = max_state (result, get_status ((double)procs, procs_thresholds) ); |
| 280 | } | 333 | } |
| 281 | 334 | ||
| 282 | if ( result == STATE_OK ) { | 335 | if ( result == STATE_OK ) { |
| @@ -301,6 +354,13 @@ main (int argc, char **argv) | |||
| 301 | if ( verbose >= 1 && strcmp(fails,"") ) | 354 | if ( verbose >= 1 && strcmp(fails,"") ) |
| 302 | printf (" [%s]", fails); | 355 | printf (" [%s]", fails); |
| 303 | 356 | ||
| 357 | if (metric == METRIC_PROCS) | ||
| 358 | printf (" | procs=%d;%s;%s;0;", procs, | ||
| 359 | warning_range ? warning_range : "", | ||
| 360 | critical_range ? critical_range : ""); | ||
| 361 | else | ||
| 362 | printf (" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit); | ||
| 363 | |||
| 304 | printf ("\n"); | 364 | printf ("\n"); |
| 305 | return result; | 365 | return result; |
| 306 | } | 366 | } |
| @@ -327,6 +387,7 @@ process_arguments (int argc, char **argv) | |||
| 327 | {"timeout", required_argument, 0, 't'}, | 387 | {"timeout", required_argument, 0, 't'}, |
| 328 | {"status", required_argument, 0, 's'}, | 388 | {"status", required_argument, 0, 's'}, |
| 329 | {"ppid", required_argument, 0, 'p'}, | 389 | {"ppid", required_argument, 0, 'p'}, |
| 390 | {"user", required_argument, 0, 'u'}, | ||
| 330 | {"command", required_argument, 0, 'C'}, | 391 | {"command", required_argument, 0, 'C'}, |
| 331 | {"vsz", required_argument, 0, 'z'}, | 392 | {"vsz", required_argument, 0, 'z'}, |
| 332 | {"rss", required_argument, 0, 'r'}, | 393 | {"rss", required_argument, 0, 'r'}, |
| @@ -338,6 +399,8 @@ process_arguments (int argc, char **argv) | |||
| 338 | {"verbose", no_argument, 0, 'v'}, | 399 | {"verbose", no_argument, 0, 'v'}, |
| 339 | {"ereg-argument-array", required_argument, 0, CHAR_MAX+1}, | 400 | {"ereg-argument-array", required_argument, 0, CHAR_MAX+1}, |
| 340 | {"input-file", required_argument, 0, CHAR_MAX+2}, | 401 | {"input-file", required_argument, 0, CHAR_MAX+2}, |
| 402 | {"no-kthreads", required_argument, 0, 'k'}, | ||
| 403 | {"traditional-filter", no_argument, 0, 'T'}, | ||
| 341 | {0, 0, 0, 0} | 404 | {0, 0, 0, 0} |
| 342 | }; | 405 | }; |
| 343 | 406 | ||
| @@ -346,7 +409,7 @@ process_arguments (int argc, char **argv) | |||
| 346 | strcpy (argv[c], "-t"); | 409 | strcpy (argv[c], "-t"); |
| 347 | 410 | ||
| 348 | while (1) { | 411 | while (1) { |
| 349 | c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", | 412 | c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T", |
| 350 | longopts, &option); | 413 | longopts, &option); |
| 351 | 414 | ||
| 352 | if (c == -1 || c == EOF) | 415 | if (c == -1 || c == EOF) |
| @@ -368,28 +431,10 @@ process_arguments (int argc, char **argv) | |||
| 368 | timeout_interval = atoi (optarg); | 431 | timeout_interval = atoi (optarg); |
| 369 | break; | 432 | break; |
| 370 | case 'c': /* critical threshold */ | 433 | case 'c': /* critical threshold */ |
| 371 | if (is_integer (optarg)) | 434 | critical_range = optarg; |
| 372 | cmax = atoi (optarg); | ||
| 373 | else if (sscanf (optarg, ":%d", &cmax) == 1) | ||
| 374 | break; | ||
| 375 | else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2) | ||
| 376 | break; | ||
| 377 | else if (sscanf (optarg, "%d:", &cmin) == 1) | ||
| 378 | break; | ||
| 379 | else | ||
| 380 | usage4 (_("Critical Process Count must be an integer!")); | ||
| 381 | break; | 435 | break; |
| 382 | case 'w': /* warning threshold */ | 436 | case 'w': /* warning threshold */ |
| 383 | if (is_integer (optarg)) | 437 | warning_range = optarg; |
| 384 | wmax = atoi (optarg); | ||
| 385 | else if (sscanf (optarg, ":%d", &wmax) == 1) | ||
| 386 | break; | ||
| 387 | else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2) | ||
| 388 | break; | ||
| 389 | else if (sscanf (optarg, "%d:", &wmin) == 1) | ||
| 390 | break; | ||
| 391 | else | ||
| 392 | usage4 (_("Warning Process Count must be an integer!")); | ||
| 393 | break; | 438 | break; |
| 394 | case 'p': /* process id */ | 439 | case 'p': /* process id */ |
| 395 | if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) { | 440 | if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) { |
| @@ -508,9 +553,15 @@ process_arguments (int argc, char **argv) | |||
| 508 | } | 553 | } |
| 509 | 554 | ||
| 510 | usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!")); | 555 | usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!")); |
| 556 | case 'k': /* linux kernel thread filter */ | ||
| 557 | kthread_filter = 1; | ||
| 558 | break; | ||
| 511 | case 'v': /* command */ | 559 | case 'v': /* command */ |
| 512 | verbose++; | 560 | verbose++; |
| 513 | break; | 561 | break; |
| 562 | case 'T': | ||
| 563 | usepid = 1; | ||
| 564 | break; | ||
| 514 | case CHAR_MAX+2: | 565 | case CHAR_MAX+2: |
| 515 | input_filename = optarg; | 566 | input_filename = optarg; |
| 516 | break; | 567 | break; |
| @@ -518,16 +569,19 @@ process_arguments (int argc, char **argv) | |||
| 518 | } | 569 | } |
| 519 | 570 | ||
| 520 | c = optind; | 571 | c = optind; |
| 521 | if (wmax == -1 && argv[c]) | 572 | if ((! warning_range) && argv[c]) |
| 522 | wmax = atoi (argv[c++]); | 573 | warning_range = argv[c++]; |
| 523 | if (cmax == -1 && argv[c]) | 574 | if ((! critical_range) && argv[c]) |
| 524 | cmax = atoi (argv[c++]); | 575 | critical_range = argv[c++]; |
| 525 | if (statopts == NULL && argv[c]) { | 576 | if (statopts == NULL && argv[c]) { |
| 526 | xasprintf (&statopts, "%s", argv[c++]); | 577 | xasprintf (&statopts, "%s", argv[c++]); |
| 527 | xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); | 578 | xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts); |
| 528 | options |= STAT; | 579 | options |= STAT; |
| 529 | } | 580 | } |
| 530 | 581 | ||
| 582 | /* this will abort in case of invalid ranges */ | ||
| 583 | set_thresholds (&procs_thresholds, warning_range, critical_range); | ||
| 584 | |||
| 531 | return validate_arguments (); | 585 | return validate_arguments (); |
| 532 | } | 586 | } |
| 533 | 587 | ||
| @@ -536,27 +590,6 @@ process_arguments (int argc, char **argv) | |||
| 536 | int | 590 | int |
| 537 | validate_arguments () | 591 | validate_arguments () |
| 538 | { | 592 | { |
| 539 | |||
| 540 | if (wmax >= 0 && wmin == -1) | ||
| 541 | wmin = 0; | ||
| 542 | if (cmax >= 0 && cmin == -1) | ||
| 543 | cmin = 0; | ||
| 544 | if (wmax >= wmin && cmax >= cmin) { /* standard ranges */ | ||
| 545 | if (wmax > cmax && cmax != -1) { | ||
| 546 | printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax); | ||
| 547 | return ERROR; | ||
| 548 | } | ||
| 549 | if (cmin > wmin && wmin != -1) { | ||
| 550 | printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin); | ||
| 551 | return ERROR; | ||
| 552 | } | ||
| 553 | } | ||
| 554 | |||
| 555 | /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */ | ||
| 556 | /* printf ("At least one threshold must be set\n"); */ | ||
| 557 | /* return ERROR; */ | ||
| 558 | /* } */ | ||
| 559 | |||
| 560 | if (options == 0) | 593 | if (options == 0) |
| 561 | options = ALL; | 594 | options = ALL; |
| 562 | 595 | ||
| @@ -579,40 +612,6 @@ validate_arguments () | |||
| 579 | } | 612 | } |
| 580 | 613 | ||
| 581 | 614 | ||
| 582 | |||
| 583 | /* Check thresholds against value */ | ||
| 584 | int | ||
| 585 | check_thresholds (int value) | ||
| 586 | { | ||
| 587 | if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { | ||
| 588 | return OK; | ||
| 589 | } | ||
| 590 | else if (cmax >= 0 && cmin >= 0 && cmax < cmin) { | ||
| 591 | if (value > cmax && value < cmin) | ||
| 592 | return STATE_CRITICAL; | ||
| 593 | } | ||
| 594 | else if (cmax >= 0 && value > cmax) { | ||
| 595 | return STATE_CRITICAL; | ||
| 596 | } | ||
| 597 | else if (cmin >= 0 && value < cmin) { | ||
| 598 | return STATE_CRITICAL; | ||
| 599 | } | ||
| 600 | |||
| 601 | if (wmax >= 0 && wmin >= 0 && wmax < wmin) { | ||
| 602 | if (value > wmax && value < wmin) { | ||
| 603 | return STATE_WARNING; | ||
| 604 | } | ||
| 605 | } | ||
| 606 | else if (wmax >= 0 && value > wmax) { | ||
| 607 | return STATE_WARNING; | ||
| 608 | } | ||
| 609 | else if (wmin >= 0 && value < wmin) { | ||
| 610 | return STATE_WARNING; | ||
| 611 | } | ||
| 612 | return STATE_OK; | ||
| 613 | } | ||
| 614 | |||
| 615 | |||
| 616 | /* convert the elapsed time to seconds */ | 615 | /* convert the elapsed time to seconds */ |
| 617 | int | 616 | int |
| 618 | convert_to_seconds(char *etime) { | 617 | convert_to_seconds(char *etime) { |
| @@ -713,6 +712,9 @@ print_help (void) | |||
| 713 | printf (" %s\n", "-v, --verbose"); | 712 | printf (" %s\n", "-v, --verbose"); |
| 714 | printf (" %s\n", _("Extra information. Up to 3 verbosity levels")); | 713 | printf (" %s\n", _("Extra information. Up to 3 verbosity levels")); |
| 715 | 714 | ||
| 715 | printf (" %s\n", "-T, --traditional"); | ||
| 716 | printf (" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe")); | ||
| 717 | |||
| 716 | printf ("\n"); | 718 | printf ("\n"); |
| 717 | printf ("%s\n", "Filters:"); | 719 | printf ("%s\n", "Filters:"); |
| 718 | printf (" %s\n", "-s, --state=STATUSFLAGS"); | 720 | printf (" %s\n", "-s, --state=STATUSFLAGS"); |
| @@ -735,6 +737,8 @@ print_help (void) | |||
| 735 | printf (" %s\n", _("Only scan for processes with args that contain the regex STRING.")); | 737 | printf (" %s\n", _("Only scan for processes with args that contain the regex STRING.")); |
| 736 | printf (" %s\n", "-C, --command=COMMAND"); | 738 | printf (" %s\n", "-C, --command=COMMAND"); |
| 737 | printf (" %s\n", _("Only scan for exact matches of COMMAND (without path).")); | 739 | printf (" %s\n", _("Only scan for exact matches of COMMAND (without path).")); |
| 740 | printf (" %s\n", "-k, --no-kthreads"); | ||
| 741 | printf (" %s\n", _("Only scan for non kernel threads (works on Linux only).")); | ||
| 738 | 742 | ||
| 739 | printf(_("\n\ | 743 | printf(_("\n\ |
| 740 | RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\ | 744 | RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\ |
| @@ -769,5 +773,5 @@ print_usage (void) | |||
| 769 | printf ("%s\n", _("Usage:")); | 773 | printf ("%s\n", _("Usage:")); |
| 770 | printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname); | 774 | printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname); |
| 771 | printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n"); | 775 | printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n"); |
| 772 | printf (" [-C command] [-t timeout] [-v]\n"); | 776 | printf (" [-C command] [-k] [-t timeout] [-v]\n"); |
| 773 | } | 777 | } |
