Fixed SF.net bug #3552839, check_procs: added -k option to ignore kernel threads
[monitoring-plugins.git] / plugins / check_procs.c
blob9de3cc25140f61ce7090cf7f8dfb62c55dc5cf03
1 /*****************************************************************************
2 *
3 * Nagios check_procs plugin
4 *
5 * License: GPL
6 * Copyright (c) 2000-2008 Nagios Plugins Development Team
7 *
8 * Description:
9 *
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.
18 * This program is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 *****************************************************************************/
34 const char *progname = "check_procs";
35 const char *program_name = "check_procs"; /* Required for coreutils libs */
36 const char *copyright = "2000-2008";
37 const char *email = "nagiosplug-devel@lists.sourceforge.net";
39 #include "common.h"
40 #include "utils.h"
41 #include "utils_cmd.h"
42 #include "regex.h"
44 #include <pwd.h>
46 int process_arguments (int, char **);
47 int validate_arguments (void);
48 int convert_to_seconds (char *);
49 void print_help (void);
50 void print_usage (void);
52 char *warning_range = NULL;
53 char *critical_range = NULL;
54 thresholds *procs_thresholds = NULL;
56 int options = 0; /* bitmask of filter criteria to test against */
57 #define ALL 1
58 #define STAT 2
59 #define PPID 4
60 #define USER 8
61 #define PROG 16
62 #define ARGS 32
63 #define VSZ 64
64 #define RSS 128
65 #define PCPU 256
66 #define ELAPSED 512
67 #define EREG_ARGS 1024
69 #define KTHREAD_PARENT "kthreadd" /* the parent process of kernel threads:
70 ppid of procs are compared to pid of this proc*/
72 /* Different metrics */
73 char *metric_name;
74 enum metric {
75 METRIC_PROCS,
76 METRIC_VSZ,
77 METRIC_RSS,
78 METRIC_CPU,
79 METRIC_ELAPSED
81 enum metric metric = METRIC_PROCS;
83 int verbose = 0;
84 int uid;
85 pid_t ppid;
86 int vsz;
87 int rss;
88 float pcpu;
89 char *statopts;
90 char *prog;
91 char *args;
92 char *input_filename = NULL;
93 regex_t re_args;
94 char *fmt;
95 char *fails;
96 char tmp[MAX_INPUT_BUFFER];
97 int kthread_filter = 0;
99 FILE *ps_input = NULL;
103 main (int argc, char **argv)
105 char *input_buffer;
106 char *input_line;
107 char *procprog;
109 pid_t mypid = 0;
110 int procuid = 0;
111 pid_t procpid = 0;
112 pid_t procppid = 0;
113 pid_t kthread_ppid = 0;
114 int procvsz = 0;
115 int procrss = 0;
116 int procseconds = 0;
117 float procpcpu = 0;
118 char procstat[8];
119 char procetime[MAX_INPUT_BUFFER] = { '\0' };
120 char *procargs;
122 const char *zombie = "Z";
124 int resultsum = 0; /* bitmask of the filter criteria met by a process */
125 int found = 0; /* counter for number of lines returned in `ps` output */
126 int procs = 0; /* counter for number of processes meeting filter criteria */
127 int pos; /* number of spaces before 'args' in `ps` output */
128 int cols; /* number of columns in ps output */
129 int expected_cols = PS_COLS - 1;
130 int warn = 0; /* number of processes in warn state */
131 int crit = 0; /* number of processes in crit state */
132 int i = 0, j = 0;
133 int result = STATE_UNKNOWN;
134 output chld_out, chld_err;
136 setlocale (LC_ALL, "");
137 bindtextdomain (PACKAGE, LOCALEDIR);
138 textdomain (PACKAGE);
139 setlocale(LC_NUMERIC, "POSIX");
141 input_buffer = malloc (MAX_INPUT_BUFFER);
142 procprog = malloc (MAX_INPUT_BUFFER);
144 xasprintf (&metric_name, "PROCS");
145 metric = METRIC_PROCS;
147 /* Parse extra opts if any */
148 argv=np_extra_opts (&argc, argv, progname);
150 if (process_arguments (argc, argv) == ERROR)
151 usage4 (_("Could not parse arguments"));
153 /* get our pid */
154 mypid = getpid();
156 /* Set signal handling and alarm timeout */
157 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
158 die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
160 (void) alarm ((unsigned) timeout_interval);
162 if (verbose >= 2)
163 printf (_("CMD: %s\n"), PS_COMMAND);
165 if (input_filename == NULL) {
166 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
167 if (chld_err.lines > 0) {
168 printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
169 exit(STATE_WARNING);
171 } else {
172 result = cmd_file_read( input_filename, &chld_out, 0);
175 /* flush first line: j starts at 1 */
176 for (j = 1; j < chld_out.lines; j++) {
177 input_line = chld_out.line[j];
179 if (verbose >= 3)
180 printf ("%s", input_line);
182 strcpy (procprog, "");
183 xasprintf (&procargs, "%s", "");
185 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
187 /* Zombie processes do not give a procprog command */
188 if ( cols < expected_cols && strstr(procstat, zombie) ) {
189 cols = expected_cols;
191 if ( cols >= expected_cols ) {
192 resultsum = 0;
193 xasprintf (&procargs, "%s", input_line + pos);
194 strip (procargs);
196 /* Some ps return full pathname for command. This removes path */
197 strcpy(procprog, base_name(procprog));
199 /* we need to convert the elapsed time to seconds */
200 procseconds = convert_to_seconds(procetime);
202 if (verbose >= 3)
203 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
204 procs, procuid, procvsz, procrss,
205 procpid, procppid, procpcpu, procstat,
206 procetime, procprog, procargs);
208 /* Ignore self */
209 if (mypid == procpid) continue;
211 /* filter kernel threads (childs of KTHREAD_PARENT)*/
212 /* TODO adapt for other OSes than GNU/Linux
213 sorry for not doing that, but I've no other OSes to test :-( */
214 if (kthread_filter == 1) {
215 /* get pid KTHREAD_PARENT */
216 if (kthread_ppid == 0 && !strcmp(procprog, KTHREAD_PARENT) )
217 kthread_ppid = procpid;
219 if (kthread_ppid == procppid) {
220 if (verbose >= 2)
221 printf ("Ignore kernel thread: pid=%d ppid=%d prog=%s args=%s\n", procpid, procppid, procprog, procargs);
222 continue;
226 if ((options & STAT) && (strstr (statopts, procstat)))
227 resultsum |= STAT;
228 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
229 resultsum |= ARGS;
230 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
231 resultsum |= EREG_ARGS;
232 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
233 resultsum |= PROG;
234 if ((options & PPID) && (procppid == ppid))
235 resultsum |= PPID;
236 if ((options & USER) && (procuid == uid))
237 resultsum |= USER;
238 if ((options & VSZ) && (procvsz >= vsz))
239 resultsum |= VSZ;
240 if ((options & RSS) && (procrss >= rss))
241 resultsum |= RSS;
242 if ((options & PCPU) && (procpcpu >= pcpu))
243 resultsum |= PCPU;
245 found++;
247 /* Next line if filters not matched */
248 if (!(options == resultsum || options == ALL))
249 continue;
251 procs++;
252 if (verbose >= 2) {
253 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
254 procuid, procvsz, procrss,
255 procpid, procppid, procpcpu, procstat,
256 procetime, procprog, procargs);
259 if (metric == METRIC_VSZ)
260 i = get_status ((double)procvsz, procs_thresholds);
261 else if (metric == METRIC_RSS)
262 i = get_status ((double)procrss, procs_thresholds);
263 /* TODO? float thresholds for --metric=CPU */
264 else if (metric == METRIC_CPU)
265 i = get_status (procpcpu, procs_thresholds);
266 else if (metric == METRIC_ELAPSED)
267 i = get_status ((double)procseconds, procs_thresholds);
269 if (metric != METRIC_PROCS) {
270 if (i == STATE_WARNING) {
271 warn++;
272 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
273 result = max_state (result, i);
275 if (i == STATE_CRITICAL) {
276 crit++;
277 xasprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
278 result = max_state (result, i);
282 /* This should not happen */
283 else if (verbose) {
284 printf(_("Not parseable: %s"), input_buffer);
288 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
289 printf (_("Unable to read output\n"));
290 return STATE_UNKNOWN;
293 if ( result == STATE_UNKNOWN )
294 result = STATE_OK;
296 /* Needed if procs found, but none match filter */
297 if ( metric == METRIC_PROCS ) {
298 result = max_state (result, get_status ((double)procs, procs_thresholds) );
301 if ( result == STATE_OK ) {
302 printf ("%s %s: ", metric_name, _("OK"));
303 } else if (result == STATE_WARNING) {
304 printf ("%s %s: ", metric_name, _("WARNING"));
305 if ( metric != METRIC_PROCS ) {
306 printf (_("%d warn out of "), warn);
308 } else if (result == STATE_CRITICAL) {
309 printf ("%s %s: ", metric_name, _("CRITICAL"));
310 if (metric != METRIC_PROCS) {
311 printf (_("%d crit, %d warn out of "), crit, warn);
314 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
316 if (strcmp(fmt,"") != 0) {
317 printf (_(" with %s"), fmt);
320 if ( verbose >= 1 && strcmp(fails,"") )
321 printf (" [%s]", fails);
323 if (metric == METRIC_PROCS)
324 printf (" | procs=%d;%s;%s;0;", procs,
325 warning_range ? warning_range : "",
326 critical_range ? critical_range : "");
327 else
328 printf (" | procs=%d;;;0; procs_warn=%d;;;0; procs_crit=%d;;;0;", procs, warn, crit);
330 printf ("\n");
331 return result;
336 /* process command-line arguments */
338 process_arguments (int argc, char **argv)
340 int c = 1;
341 char *user;
342 struct passwd *pw;
343 int option = 0;
344 int err;
345 int cflags = REG_NOSUB | REG_EXTENDED;
346 char errbuf[MAX_INPUT_BUFFER];
347 char *temp_string;
348 int i=0;
349 static struct option longopts[] = {
350 {"warning", required_argument, 0, 'w'},
351 {"critical", required_argument, 0, 'c'},
352 {"metric", required_argument, 0, 'm'},
353 {"timeout", required_argument, 0, 't'},
354 {"status", required_argument, 0, 's'},
355 {"ppid", required_argument, 0, 'p'},
356 {"user", required_argument, 0, 'u'},
357 {"command", required_argument, 0, 'C'},
358 {"vsz", required_argument, 0, 'z'},
359 {"rss", required_argument, 0, 'r'},
360 {"pcpu", required_argument, 0, 'P'},
361 {"elapsed", required_argument, 0, 'e'},
362 {"argument-array", required_argument, 0, 'a'},
363 {"help", no_argument, 0, 'h'},
364 {"version", no_argument, 0, 'V'},
365 {"verbose", no_argument, 0, 'v'},
366 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
367 {"input-file", required_argument, 0, CHAR_MAX+2},
368 {"no-kthreads", required_argument, 0, 'k'},
369 {0, 0, 0, 0}
372 for (c = 1; c < argc; c++)
373 if (strcmp ("-to", argv[c]) == 0)
374 strcpy (argv[c], "-t");
376 while (1) {
377 c = getopt_long (argc, argv, "Vvhkt:c:w:p:s:u:C:a:z:r:m:P:",
378 longopts, &option);
380 if (c == -1 || c == EOF)
381 break;
383 switch (c) {
384 case '?': /* help */
385 usage5 ();
386 case 'h': /* help */
387 print_help ();
388 exit (STATE_OK);
389 case 'V': /* version */
390 print_revision (progname, NP_VERSION);
391 exit (STATE_OK);
392 case 't': /* timeout period */
393 if (!is_integer (optarg))
394 usage2 (_("Timeout interval must be a positive integer"), optarg);
395 else
396 timeout_interval = atoi (optarg);
397 break;
398 case 'c': /* critical threshold */
399 critical_range = optarg;
400 break;
401 case 'w': /* warning threshold */
402 warning_range = optarg;
403 break;
404 case 'p': /* process id */
405 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
406 xasprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
407 options |= PPID;
408 break;
410 usage4 (_("Parent Process ID must be an integer!"));
411 case 's': /* status */
412 if (statopts)
413 break;
414 else
415 statopts = optarg;
416 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
417 options |= STAT;
418 break;
419 case 'u': /* user or user id */
420 if (is_integer (optarg)) {
421 uid = atoi (optarg);
422 pw = getpwuid ((uid_t) uid);
423 /* check to be sure user exists */
424 if (pw == NULL)
425 usage2 (_("UID was not found"), optarg);
427 else {
428 pw = getpwnam (optarg);
429 /* check to be sure user exists */
430 if (pw == NULL)
431 usage2 (_("User name was not found"), optarg);
432 /* then get uid */
433 uid = pw->pw_uid;
435 user = pw->pw_name;
436 xasprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
437 uid, user);
438 options |= USER;
439 break;
440 case 'C': /* command */
441 /* TODO: allow this to be passed in with --metric */
442 if (prog)
443 break;
444 else
445 prog = optarg;
446 xasprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
447 prog);
448 options |= PROG;
449 break;
450 case 'a': /* args (full path name with args) */
451 /* TODO: allow this to be passed in with --metric */
452 if (args)
453 break;
454 else
455 args = optarg;
456 xasprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
457 options |= ARGS;
458 break;
459 case CHAR_MAX+1:
460 err = regcomp(&re_args, optarg, cflags);
461 if (err != 0) {
462 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
463 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
465 /* Strip off any | within the regex optarg */
466 temp_string = strdup(optarg);
467 while(temp_string[i]!='\0'){
468 if(temp_string[i]=='|')
469 temp_string[i]=',';
470 i++;
472 xasprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
473 options |= EREG_ARGS;
474 break;
475 case 'r': /* RSS */
476 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
477 xasprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
478 options |= RSS;
479 break;
481 usage4 (_("RSS must be an integer!"));
482 case 'z': /* VSZ */
483 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
484 xasprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
485 options |= VSZ;
486 break;
488 usage4 (_("VSZ must be an integer!"));
489 case 'P': /* PCPU */
490 /* TODO: -P 1.5.5 is accepted */
491 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
492 xasprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
493 options |= PCPU;
494 break;
496 usage4 (_("PCPU must be a float!"));
497 case 'm':
498 xasprintf (&metric_name, "%s", optarg);
499 if ( strcmp(optarg, "PROCS") == 0) {
500 metric = METRIC_PROCS;
501 break;
503 else if ( strcmp(optarg, "VSZ") == 0) {
504 metric = METRIC_VSZ;
505 break;
507 else if ( strcmp(optarg, "RSS") == 0 ) {
508 metric = METRIC_RSS;
509 break;
511 else if ( strcmp(optarg, "CPU") == 0 ) {
512 metric = METRIC_CPU;
513 break;
515 else if ( strcmp(optarg, "ELAPSED") == 0) {
516 metric = METRIC_ELAPSED;
517 break;
520 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
521 case 'k': /* linux kernel thread filter */
522 kthread_filter = 1;
523 break;
524 case 'v': /* command */
525 verbose++;
526 break;
527 case CHAR_MAX+2:
528 input_filename = optarg;
529 break;
533 c = optind;
534 if ((! warning_range) && argv[c])
535 warning_range = argv[c++];
536 if ((! critical_range) && argv[c])
537 critical_range = argv[c++];
538 if (statopts == NULL && argv[c]) {
539 xasprintf (&statopts, "%s", argv[c++]);
540 xasprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
541 options |= STAT;
544 /* this will abort in case of invalid ranges */
545 set_thresholds (&procs_thresholds, warning_range, critical_range);
547 return validate_arguments ();
553 validate_arguments ()
555 if (options == 0)
556 options = ALL;
558 if (statopts==NULL)
559 statopts = strdup("");
561 if (prog==NULL)
562 prog = strdup("");
564 if (args==NULL)
565 args = strdup("");
567 if (fmt==NULL)
568 fmt = strdup("");
570 if (fails==NULL)
571 fails = strdup("");
573 return options;
577 /* convert the elapsed time to seconds */
579 convert_to_seconds(char *etime) {
581 char *ptr;
582 int total;
584 int hyphcnt;
585 int coloncnt;
586 int days;
587 int hours;
588 int minutes;
589 int seconds;
591 hyphcnt = 0;
592 coloncnt = 0;
593 days = 0;
594 hours = 0;
595 minutes = 0;
596 seconds = 0;
598 for (ptr = etime; *ptr != '\0'; ptr++) {
600 if (*ptr == '-') {
601 hyphcnt++;
602 continue;
604 if (*ptr == ':') {
605 coloncnt++;
606 continue;
610 if (hyphcnt > 0) {
611 sscanf(etime, "%d-%d:%d:%d",
612 &days, &hours, &minutes, &seconds);
613 /* linux 2.6.5/2.6.6 reporting some processes with infinite
614 * elapsed times for some reason */
615 if (days == 49710) {
616 return 0;
618 } else {
619 if (coloncnt == 2) {
620 sscanf(etime, "%d:%d:%d",
621 &hours, &minutes, &seconds);
622 } else if (coloncnt == 1) {
623 sscanf(etime, "%d:%d",
624 &minutes, &seconds);
628 total = (days * 86400) +
629 (hours * 3600) +
630 (minutes * 60) +
631 seconds;
633 if (verbose >= 3 && metric == METRIC_ELAPSED) {
634 printf("seconds: %d\n", total);
636 return total;
640 void
641 print_help (void)
643 print_revision (progname, NP_VERSION);
645 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
646 printf (COPYRIGHT, copyright, email);
648 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
649 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
650 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
652 printf ("\n\n");
654 print_usage ();
656 printf (UT_HELP_VRSN);
657 printf (UT_EXTRA_OPTS);
658 printf (" %s\n", "-w, --warning=RANGE");
659 printf (" %s\n", _("Generate warning state if metric is outside this range"));
660 printf (" %s\n", "-c, --critical=RANGE");
661 printf (" %s\n", _("Generate critical state if metric is outside this range"));
662 printf (" %s\n", "-m, --metric=TYPE");
663 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
664 printf (" %s\n", _("PROCS - number of processes (default)"));
665 printf (" %s\n", _("VSZ - virtual memory size"));
666 printf (" %s\n", _("RSS - resident set memory size"));
667 printf (" %s\n", _("CPU - percentage CPU"));
668 /* only linux etime is support currently */
669 #if defined( __linux__ )
670 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
671 #endif /* defined(__linux__) */
672 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
674 printf (" %s\n", "-v, --verbose");
675 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
677 printf ("\n");
678 printf ("%s\n", "Filters:");
679 printf (" %s\n", "-s, --state=STATUSFLAGS");
680 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
681 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
682 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
683 printf (" %s\n", "-p, --ppid=PPID");
684 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
685 printf (" %s\n", "-z, --vsz=VSZ");
686 printf (" %s\n", _("Only scan for processes with VSZ higher than indicated."));
687 printf (" %s\n", "-r, --rss=RSS");
688 printf (" %s\n", _("Only scan for processes with RSS higher than indicated."));
689 printf (" %s\n", "-P, --pcpu=PCPU");
690 printf (" %s\n", _("Only scan for processes with PCPU higher than indicated."));
691 printf (" %s\n", "-u, --user=USER");
692 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
693 printf (" %s\n", "-a, --argument-array=STRING");
694 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
695 printf (" %s\n", "--ereg-argument-array=STRING");
696 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
697 printf (" %s\n", "-C, --command=COMMAND");
698 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
699 printf (" %s\n", "-k, --no-kthreads");
700 printf (" %s\n", _("Only scan for non kernel threads (works on Linux only)."));
702 printf(_("\n\
703 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
704 specified 'max:min', a warning status will be generated if the\n\
705 count is inside the specified range\n\n"));
707 printf(_("\
708 This plugin checks the number of currently running processes and\n\
709 generates WARNING or CRITICAL states if the process count is outside\n\
710 the specified threshold ranges. The process count can be filtered by\n\
711 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
712 be the total number of running processes\n\n"));
714 printf ("%s\n", _("Examples:"));
715 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
716 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
717 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
718 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
719 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
720 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
721 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
722 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
723 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
724 printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
726 printf (UT_SUPPORT);
729 void
730 print_usage (void)
732 printf ("%s\n", _("Usage:"));
733 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
734 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
735 printf (" [-C command] [-k] [-t timeout] [-v]\n");