summaryrefslogtreecommitdiffstats
path: root/plugins/check_procs.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_procs.c')
-rw-r--r--plugins/check_procs.c190
1 files changed, 97 insertions, 93 deletions
diff --git a/plugins/check_procs.c b/plugins/check_procs.c
index 2f2dcc5..d09bd8b 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
46int process_arguments (int, char **); 51int process_arguments (int, char **);
47int validate_arguments (void); 52int validate_arguments (void);
48int check_thresholds (int);
49int convert_to_seconds (char *); 53int convert_to_seconds (char *);
50void print_help (void); 54void print_help (void);
51void print_usage (void); 55void print_usage (void);
52 56
53int wmax = -1; 57char *warning_range = NULL;
54int cmax = -1; 58char *critical_range = NULL;
55int wmin = -1; 59thresholds *procs_thresholds = NULL;
56int cmin = -1;
57 60
58int options = 0; /* bitmask of filter criteria to test against */ 61int 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 */
71char *metric_name; 78char *metric_name;
72enum metric { 79enum metric {
@@ -92,9 +99,21 @@ regex_t re_args;
92char *fmt; 99char *fmt;
93char *fails; 100char *fails;
94char tmp[MAX_INPUT_BUFFER]; 101char tmp[MAX_INPUT_BUFFER];
102int kthread_filter = 0;
103int usepid = 0; /* whether to test for pid or /proc/pid/exe */
95 104
96FILE *ps_input = NULL; 105FILE *ps_input = NULL;
97 106
107static int
108stat_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
99int 118int
100main (int argc, char **argv) 119main (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)
536int 590int
537validate_arguments () 591validate_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 */
584int
585check_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 */
617int 616int
618convert_to_seconds(char *etime) { 617convert_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\
740RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\ 744RANGEs 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}