Merge pull request #2044 from RincewindsHat/fix/fedora-rpm-build
[monitoring-plugins.git] / plugins / check_procs.c
blob5777ba07079d09144fb8c46326ac5c31d6134eab
1 /*****************************************************************************
3 * Monitoring check_procs plugin
5 * License: GPL
6 * Copyright (c) 2000-2024 Monitoring Plugins Development Team
8 * Description:
10 * This file contains the check_procs plugin
12 * Checks all processes and generates WARNING or CRITICAL states if the
13 * specified metric is outside the required threshold ranges. The metric
14 * defaults to number of processes. Search filters can be applied to limit
15 * the processes to check.
17 * The parent process, check_procs itself and any child process of
18 * check_procs (ps) are excluded from any checks to prevent false positives.
21 * This program is free software: you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published by
23 * the Free Software Foundation, either version 3 of the License, or
24 * (at your option) any later version.
26 * This program is distributed in the hope that it will be useful,
27 * but WITHOUT ANY WARRANTY; without even the implied warranty of
28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
29 * GNU General Public License for more details.
31 * You should have received a copy of the GNU General Public License
32 * along with this program. If not, see <http://www.gnu.org/licenses/>.
35 *****************************************************************************/
37 const char *progname = "check_procs";
38 const char *program_name = "check_procs"; /* Required for coreutils libs */
39 const char *copyright = "2000-2024";
40 const char *email = "devel@monitoring-plugins.org";
42 #include "common.h"
43 #include "utils.h"
44 #include "utils_cmd.h"
45 #include "regex.h"
47 #include <pwd.h>
48 #include <errno.h>
50 #ifdef HAVE_SYS_STAT_H
51 #include <sys/stat.h>
52 #endif
54 int process_arguments (int, char **);
55 int validate_arguments (void);
56 int convert_to_seconds (char *);
57 void print_help (void);
58 void print_usage (void);
60 char *warning_range = NULL;
61 char *critical_range = NULL;
62 thresholds *procs_thresholds = NULL;
64 int options = 0; /* bitmask of filter criteria to test against */
65 #define ALL 1
66 #define STAT 2
67 #define PPID 4
68 #define USER 8
69 #define PROG 16
70 #define ARGS 32
71 #define VSZ 64
72 #define RSS 128
73 #define PCPU 256
74 #define ELAPSED 512
75 #define EREG_ARGS 1024
76 #define EXCLUDE_PROGS 2048
78 #define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads:
79 ppid of procs are compared to pid of this proc*/
81 /* Different metrics */
82 char *metric_name;
83 enum metric {
84 METRIC_PROCS,
85 METRIC_VSZ,
86 METRIC_RSS,
87 METRIC_CPU,
88 METRIC_ELAPSED
90 enum metric metric = METRIC_PROCS;
92 int verbose = 0;
93 int uid;
94 pid_t ppid;
95 int vsz;
96 int rss;
97 float pcpu;
98 char *statopts;
99 char *prog;
100 char *exclude_progs;
101 char **exclude_progs_arr = NULL;
102 char exclude_progs_counter = 0;
103 char *args;
104 char *input_filename = NULL;
105 regex_t re_args;
106 char *fmt;
107 char *fails;
108 char tmp[MAX_INPUT_BUFFER];
109 int kthread_filter = 0;
110 int usepid = 0; /* whether to test for pid or /proc/pid/exe */
112 FILE *ps_input = NULL;
114 static int
115 stat_exe (const pid_t pid, struct stat *buf) {
116 char *path;
117 int ret;
118 xasprintf(&path, "/proc/%d/exe", pid);
119 ret = stat(path, buf);
120 free(path);
121 return ret;
126 main (int argc, char **argv)
128 char *input_buffer;
129 char *input_line;
130 char *procprog;
132 pid_t mypid = 0;
133 pid_t myppid = 0;
134 struct stat statbuf;
135 dev_t mydev = 0;
136 ino_t myino = 0;
137 int procuid = 0;
138 pid_t procpid = 0;
139 pid_t procppid = 0;
140 pid_t kthread_ppid = 0;
141 int procvsz = 0;
142 int procrss = 0;
143 int procseconds = 0;
144 float procpcpu = 0;
145 char procstat[8];
146 char procetime[MAX_INPUT_BUFFER] = { '\0' };
147 char *procargs;
149 const char *zombie = "Z";
151 int resultsum = 0; /* bitmask of the filter criteria met by a process */
152 int found = 0; /* counter for number of lines returned in `ps` output */
153 int procs = 0; /* counter for number of processes meeting filter criteria */
154 int pos; /* number of spaces before 'args' in `ps` output */
155 int cols; /* number of columns in ps output */
156 int expected_cols = PS_COLS - 1;
157 int warn = 0; /* number of processes in warn state */
158 int crit = 0; /* number of processes in crit state */
159 int i = 0;
160 int result = STATE_UNKNOWN;
161 int ret = 0;
162 output chld_out, chld_err;
164 setlocale (LC_ALL, "");
165 bindtextdomain (PACKAGE, LOCALEDIR);
166 textdomain (PACKAGE);
167 setlocale(LC_NUMERIC, "POSIX");
169 input_buffer = malloc (MAX_INPUT_BUFFER);
170 procprog = malloc (MAX_INPUT_BUFFER);
172 xasprintf (&metric_name, "PROCS");
173 metric = METRIC_PROCS;
175 /* Parse extra opts if any */
176 argv=np_extra_opts (&argc, argv, progname);
178 if (process_arguments (argc, argv) == ERROR)
179 usage4 (_("Could not parse arguments"));
181 /* find ourself */
182 mypid = getpid();
183 myppid = getppid();
184 if (usepid || stat_exe(mypid, &statbuf) == -1) {
185 /* usepid might have been set by -T */
186 usepid = 1;
187 } else {
188 usepid = 0;
189 mydev = statbuf.st_dev;
190 myino = statbuf.st_ino;
193 /* Set signal handling and alarm timeout */
194 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
195 die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
197 (void) alarm ((unsigned) timeout_interval);
199 if (verbose >= 2)
200 printf (_("CMD: %s\n"), PS_COMMAND);
202 if (input_filename == NULL) {
203 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
204 if (chld_err.lines > 0) {
205 printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
206 exit(STATE_WARNING);
208 } else {
209 result = cmd_file_read( input_filename, &chld_out, 0);
212 /* flush first line: j starts at 1 */
213 for (size_t j = 1; j < chld_out.lines; j++) {
214 input_line = chld_out.line[j];
216 if (verbose >= 3)
217 printf ("%s", input_line);
219 strcpy (procprog, "");
220 xasprintf (&procargs, "%s", "");
222 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
224 /* Zombie processes do not give a procprog command */
225 if ( cols < expected_cols && strstr(procstat, zombie) ) {
226 cols = expected_cols;
228 if ( cols >= expected_cols ) {
229 resultsum = 0;
230 xasprintf (&procargs, "%s", input_line + pos);
231 strip (procargs);
233 /* Some ps return full pathname for command. This removes path */
234 strcpy(procprog, base_name(procprog));
236 /* we need to convert the elapsed time to seconds */
237 procseconds = convert_to_seconds(procetime);
239 if (verbose >= 3)
240 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
241 procs, procuid, procvsz, procrss,
242 procpid, procppid, procpcpu, procstat,
243 procetime, procprog, procargs);
245 /* Ignore self */
246 if ((usepid && mypid == procpid) ||
247 ( ((!usepid) && ((ret = stat_exe(procpid, &statbuf) != -1) && statbuf.st_dev == mydev && statbuf.st_ino == myino)) ||
248 (ret == -1 && errno == ENOENT))
250 if (verbose >= 3)
251 printf("not considering - is myself or gone\n");
252 continue;
254 /* Ignore parent*/
255 else if (myppid == procpid) {
256 if (verbose >= 3)
257 printf("not considering - is parent\n");
258 continue;
261 /* Ignore our own children */
262 if (procppid == mypid) {
263 if (verbose >= 3)
264 printf("not considering - is our child\n");
265 continue;
268 /* Ignore excluded processes by name */
269 if(options & EXCLUDE_PROGS) {
270 int found = 0;
271 int i = 0;
273 for(i=0; i < (exclude_progs_counter); i++) {
274 if(!strcmp(procprog, exclude_progs_arr[i])) {
275 found = 1;
278 if(found == 0) {
279 resultsum |= EXCLUDE_PROGS;
280 } else
282 if(verbose >= 3)
283 printf("excluding - by ignorelist\n");
287 /* filter kernel threads (children of KTHREAD_PARENT)*/
288 /* TODO adapt for other OSes than GNU/Linux
289 sorry for not doing that, but I've no other OSes to test :-( */
290 if (kthread_filter == 1) {
291 /* get pid KTHREAD_PARENT */
292 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT) )
293 kthread_ppid = procpid;
295 if (kthread_ppid == procppid) {
296 if (verbose >= 2)
297 printf ("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs);
298 continue;
302 if ((options & STAT) && (strstr (procstat, statopts)))
303 resultsum |= STAT;
304 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
305 resultsum |= ARGS;
306 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
307 resultsum |= EREG_ARGS;
308 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
309 resultsum |= PROG;
310 if ((options & PPID) && (procppid == ppid))
311 resultsum |= PPID;
312 if ((options & USER) && (procuid == uid))
313 resultsum |= USER;
314 if ((options & VSZ) && (procvsz >= vsz))
315 resultsum |= VSZ;
316 if ((options & RSS) && (procrss >= rss))
317 resultsum |= RSS;
318 if ((options & PCPU) && (procpcpu >= pcpu))
319 resultsum |= PCPU;
321 found++;
323 /* Next line if filters not matched */
324 if (!(options == resultsum || options == ALL))
325 continue;
327 procs++;
328 if (verbose >= 2) {
329 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
330 procuid, procvsz, procrss,
331 procpid, procppid, procpcpu, procstat,
332 procetime, procprog, procargs);
335 if (metric == METRIC_VSZ)
336 i = get_status ((double)procvsz, procs_thresholds);
337 else if (metric == METRIC_RSS)
338 i = get_status ((double)procrss, procs_thresholds);
339 /* TODO? float thresholds for --metric=CPU */
340 else if (metric == METRIC_CPU)
341 i = get_status (procpcpu, procs_thresholds);
342 else if (metric == METRIC_ELAPSED)
343 i = get_status ((double)procseconds, procs_thresholds);
345 if (metric != METRIC_PROCS) {
346 if (i == STATE_WARNING) {
347 warn++;
348 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
349 result = max_state (result, i);
351 if (i == STATE_CRITICAL) {
352 crit++;
353 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
354 result = max_state (result, i);
358 /* This should not happen */
359 else if (verbose) {
360 printf(_("Not parseable: %s"), input_buffer);
364 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
365 printf (_("Unable to read output\n"));
366 return STATE_UNKNOWN;
369 if ( result == STATE_UNKNOWN )
370 result = STATE_OK;
372 /* Needed if procs found, but none match filter */
373 if ( metric == METRIC_PROCS ) {
374 result = max_state (result, get_status ((double)procs, procs_thresholds) );
377 if ( result == STATE_OK ) {
378 printf ("%s %s: ", metric_name, _("OK"));
379 } else if (result == STATE_WARNING) {
380 printf ("%s %s: ", metric_name, _("WARNING"));
381 if ( metric != METRIC_PROCS ) {
382 printf (_("%d warn out of "), warn);
384 } else if (result == STATE_CRITICAL) {
385 printf ("%s %s: ", metric_name, _("CRITICAL"));
386 if (metric != METRIC_PROCS) {
387 printf (_("%d crit, %d warn out of "), crit, warn);
390 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
392 if (strcmp(fmt,"") != 0) {
393 printf (_(" with %s"), fmt);
396 if ( verbose >= 1 && strcmp(fails,"") )
397 printf (" [%s]", fails);
399 if (metric == METRIC_PROCS)
400 printf (" | procs=%d;%s;%s;0;", procs,
401 warning_range ? warning_range : "",
402 critical_range ? critical_range : "");
403 else
404 printf (" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
406 printf ("\n");
407 return result;
412 /* process command-line arguments */
414 process_arguments (int argc, char **argv)
416 int c = 1;
417 char *user;
418 struct passwd *pw;
419 int option = 0;
420 int err;
421 int cflags = REG_NOSUB | REG_EXTENDED;
422 char errbuf[MAX_INPUT_BUFFER];
423 char *temp_string;
424 int i=0;
425 static struct option longopts[] = {
426 {"warning", required_argument, 0, 'w'},
427 {"critical", required_argument, 0, 'c'},
428 {"metric", required_argument, 0, 'm'},
429 {"timeout", required_argument, 0, 't'},
430 {"status", required_argument, 0, 's'},
431 {"ppid", required_argument, 0, 'p'},
432 {"user", required_argument, 0, 'u'},
433 {"command", required_argument, 0, 'C'},
434 {"vsz", required_argument, 0, 'z'},
435 {"rss", required_argument, 0, 'r'},
436 {"pcpu", required_argument, 0, 'P'},
437 {"elapsed", required_argument, 0, 'e'},
438 {"argument-array", required_argument, 0, 'a'},
439 {"help", no_argument, 0, 'h'},
440 {"version", no_argument, 0, 'V'},
441 {"verbose", no_argument, 0, 'v'},
442 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
443 {"input-file", required_argument, 0, CHAR_MAX+2},
444 {"no-kthreads", required_argument, 0, 'k'},
445 {"traditional-filter", no_argument, 0, 'T'},
446 {"exclude-process", required_argument, 0, 'X'},
447 {0, 0, 0, 0}
450 for (c = 1; c < argc; c++)
451 if (strcmp ("-to", argv[c]) == 0)
452 strcpy (argv[c], "-t");
454 while (1) {
455 c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:T:X:",
456 longopts, &option);
458 if (c == -1 || c == EOF)
459 break;
461 switch (c) {
462 case '?': /* help */
463 usage5 ();
464 case 'h': /* help */
465 print_help ();
466 exit (STATE_UNKNOWN);
467 case 'V': /* version */
468 print_revision (progname, NP_VERSION);
469 exit (STATE_UNKNOWN);
470 case 't': /* timeout period */
471 if (!is_integer (optarg))
472 usage2 (_("Timeout interval must be a positive integer"), optarg);
473 else
474 timeout_interval = atoi (optarg);
475 break;
476 case 'c': /* critical threshold */
477 critical_range = optarg;
478 break;
479 case 'w': /* warning threshold */
480 warning_range = optarg;
481 break;
482 case 'p': /* process id */
483 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
484 xasprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
485 options |= PPID;
486 break;
488 usage4 (_("Parent Process ID must be an integer!"));
489 case 's': /* status */
490 if (statopts)
491 break;
492 else
493 statopts = optarg;
494 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
495 options |= STAT;
496 break;
497 case 'u': /* user or user id */
498 if (is_integer (optarg)) {
499 uid = atoi (optarg);
500 pw = getpwuid ((uid_t) uid);
501 /* check to be sure user exists */
502 if (pw == NULL)
503 usage2 (_("UID was not found"), optarg);
505 else {
506 pw = getpwnam (optarg);
507 /* check to be sure user exists */
508 if (pw == NULL)
509 usage2 (_("User name was not found"), optarg);
510 /* then get uid */
511 uid = pw->pw_uid;
513 user = pw->pw_name;
514 xasprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
515 uid, user);
516 options |= USER;
517 break;
518 case 'C': /* command */
519 /* TODO: allow this to be passed in with --metric */
520 if (prog)
521 break;
522 else
523 prog = optarg;
524 xasprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
525 prog);
526 options |= PROG;
527 break;
528 case 'X':
529 if(exclude_progs)
530 break;
531 else
532 exclude_progs = optarg;
533 xasprintf (&fmt, _("%s%sexclude progs '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
534 exclude_progs);
535 char *p = strtok(exclude_progs, ",");
537 while(p){
538 exclude_progs_arr = realloc(exclude_progs_arr, sizeof(char*) * ++exclude_progs_counter);
539 exclude_progs_arr[exclude_progs_counter-1] = p;
540 p = strtok(NULL, ",");
543 options |= EXCLUDE_PROGS;
544 break;
545 case 'a': /* args (full path name with args) */
546 /* TODO: allow this to be passed in with --metric */
547 if (args)
548 break;
549 else
550 args = optarg;
551 xasprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
552 options |= ARGS;
553 break;
554 case CHAR_MAX+1:
555 err = regcomp(&re_args, optarg, cflags);
556 if (err != 0) {
557 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
558 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
560 /* Strip off any | within the regex optarg */
561 temp_string = strdup(optarg);
562 while(temp_string[i]!='\0'){
563 if(temp_string[i]=='|')
564 temp_string[i]=',';
565 i++;
567 xasprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
568 options |= EREG_ARGS;
569 break;
570 case 'r': /* RSS */
571 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
572 xasprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
573 options |= RSS;
574 break;
576 usage4 (_("RSS must be an integer!"));
577 case 'z': /* VSZ */
578 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
579 xasprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
580 options |= VSZ;
581 break;
583 usage4 (_("VSZ must be an integer!"));
584 case 'P': /* PCPU */
585 /* TODO: -P 1.5.5 is accepted */
586 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
587 xasprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
588 options |= PCPU;
589 break;
591 usage4 (_("PCPU must be a float!"));
592 case 'm':
593 xasprintf (&metric_name, "%s", optarg);
594 if ( strcmp(optarg, "PROCS") == 0) {
595 metric = METRIC_PROCS;
596 break;
598 else if ( strcmp(optarg, "VSZ") == 0) {
599 metric = METRIC_VSZ;
600 break;
602 else if ( strcmp(optarg, "RSS") == 0 ) {
603 metric = METRIC_RSS;
604 break;
606 else if ( strcmp(optarg, "CPU") == 0 ) {
607 metric = METRIC_CPU;
608 break;
610 else if ( strcmp(optarg, "ELAPSED") == 0) {
611 metric = METRIC_ELAPSED;
612 break;
615 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
616 case 'k': /* linux kernel thread filter */
617 kthread_filter = 1;
618 break;
619 case 'v': /* command */
620 verbose++;
621 break;
622 case 'T':
623 usepid = 1;
624 break;
625 case CHAR_MAX+2:
626 input_filename = optarg;
627 break;
631 c = optind;
632 if ((! warning_range) && argv[c])
633 warning_range = argv[c++];
634 if ((! critical_range) && argv[c])
635 critical_range = argv[c++];
636 if (statopts == NULL && argv[c]) {
637 xasprintf (&statopts, "%s", argv[c++]);
638 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
639 options |= STAT;
642 /* this will abort in case of invalid ranges */
643 set_thresholds (&procs_thresholds, warning_range, critical_range);
645 return validate_arguments ();
651 validate_arguments ()
653 if (options == 0)
654 options = ALL;
656 if (statopts==NULL)
657 statopts = strdup("");
659 if (prog==NULL)
660 prog = strdup("");
662 if (args==NULL)
663 args = strdup("");
665 if (fmt==NULL)
666 fmt = strdup("");
668 if (fails==NULL)
669 fails = strdup("");
671 return options;
675 /* convert the elapsed time to seconds */
677 convert_to_seconds(char *etime) {
679 char *ptr;
680 int total;
682 int hyphcnt;
683 int coloncnt;
684 int days;
685 int hours;
686 int minutes;
687 int seconds;
689 hyphcnt = 0;
690 coloncnt = 0;
691 days = 0;
692 hours = 0;
693 minutes = 0;
694 seconds = 0;
696 for (ptr = etime; *ptr != '\0'; ptr++) {
698 if (*ptr == '-') {
699 hyphcnt++;
700 continue;
702 if (*ptr == ':') {
703 coloncnt++;
704 continue;
708 if (hyphcnt > 0) {
709 sscanf(etime, "%d-%d:%d:%d",
710 &days, &hours, &minutes, &seconds);
711 /* linux 2.6.5/2.6.6 reporting some processes with infinite
712 * elapsed times for some reason */
713 if (days == 49710) {
714 return 0;
716 } else {
717 if (coloncnt == 2) {
718 sscanf(etime, "%d:%d:%d",
719 &hours, &minutes, &seconds);
720 } else if (coloncnt == 1) {
721 sscanf(etime, "%d:%d",
722 &minutes, &seconds);
726 total = (days * 86400) +
727 (hours * 3600) +
728 (minutes * 60) +
729 seconds;
731 if (verbose >= 3 && metric == METRIC_ELAPSED) {
732 printf("seconds: %d\n", total);
734 return total;
738 void
739 print_help (void)
741 print_revision (progname, NP_VERSION);
743 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
744 printf (COPYRIGHT, copyright, email);
746 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
747 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
748 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
750 printf ("\n\n");
752 printf ("%s\n", _("The parent process, check_procs itself and any child process of check_procs (ps)"));
753 printf ("%s\n", _("are excluded from any checks to prevent false positives."));
755 printf ("\n\n");
757 print_usage ();
759 printf (UT_HELP_VRSN);
760 printf (UT_EXTRA_OPTS);
761 printf (" %s\n", "-w, --warning=RANGE");
762 printf (" %s\n", _("Generate warning state if metric is outside this range"));
763 printf (" %s\n", "-c, --critical=RANGE");
764 printf (" %s\n", _("Generate critical state if metric is outside this range"));
765 printf (" %s\n", "-m, --metric=TYPE");
766 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
767 printf (" %s\n", _("PROCS - number of processes (default)"));
768 printf (" %s\n", _("VSZ - virtual memory size"));
769 printf (" %s\n", _("RSS - resident set memory size"));
770 printf (" %s\n", _("CPU - percentage CPU"));
771 /* only linux etime is support currently */
772 #if defined( __linux__ )
773 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
774 #endif /* defined(__linux__) */
775 printf (UT_PLUG_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
777 printf (" %s\n", "-v, --verbose");
778 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
780 printf (" %s\n", "-T, --traditional");
781 printf (" %s\n", _("Filter own process the traditional way by PID instead of /proc/pid/exe"));
783 printf ("\n");
784 printf ("%s\n", "Filters:");
785 printf (" %s\n", "-s, --state=STATUSFLAGS");
786 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
787 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
788 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
789 printf (" %s\n", "-p, --ppid=PPID");
790 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
791 printf (" %s\n", "-z, --vsz=VSZ");
792 printf (" %s\n", _("Only scan for processes with VSZ higher than indicated."));
793 printf (" %s\n", "-r, --rss=RSS");
794 printf (" %s\n", _("Only scan for processes with RSS higher than indicated."));
795 printf (" %s\n", "-P, --pcpu=PCPU");
796 printf (" %s\n", _("Only scan for processes with PCPU higher than indicated."));
797 printf (" %s\n", "-u, --user=USER");
798 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
799 printf (" %s\n", "-a, --argument-array=STRING");
800 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
801 printf (" %s\n", "--ereg-argument-array=STRING");
802 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
803 printf (" %s\n", "-C, --command=COMMAND");
804 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
805 printf (" %s\n", "-X, --exclude-process");
806 printf (" %s\n", _("Exclude processes which match this comma separated list"));
807 printf (" %s\n", "-k, --no-kthreads");
808 printf (" %s\n", _("Only scan for non kernel threads (works on Linux only)."));
810 printf(_("\n\
811 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
812 specified 'max:min', a warning status will be generated if the\n\
813 count is inside the specified range\n\n"));
815 printf(_("\
816 This plugin checks the number of currently running processes and\n\
817 generates WARNING or CRITICAL states if the process count is outside\n\
818 the specified threshold ranges. The process count can be filtered by\n\
819 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
820 be the total number of running processes\n\n"));
822 printf ("%s\n", _("Examples:"));
823 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
824 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
825 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
826 printf (" %s\n", "check_procs -c 1: -C sshd");
827 printf (" %s\n", _("Critical if not at least 1 process with command sshd"));
828 printf (" %s\n", "check_procs -w 1024 -c 1: -C sshd");
829 printf (" %s\n", _("Warning if > 1024 processes with command name sshd."));
830 printf (" %s\n\n", _("Critical if < 1 processes with command name sshd."));
831 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
832 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
833 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
834 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
835 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
836 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
837 printf (" %s\n", _("Alert if CPU of any processes over 10\% or 20\%"));
839 printf (UT_SUPPORT);
842 void
843 print_usage (void)
845 printf ("%s\n", _("Usage:"));
846 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
847 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
848 printf (" [-C command] [-X process_to_exclude] [-k] [-t timeout] [-v]\n");