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
11 *
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.
16 *
17 *
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.
22 *
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.
27 *
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/>.
30 *
31 *
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 check_thresholds (int);
49 int convert_to_seconds (char *);
50 void print_help (void);
51 void print_usage (void);
53 int wmax = -1;
54 int cmax = -1;
55 int wmin = -1;
56 int cmin = -1;
58 int options = 0; /* bitmask of filter criteria to test against */
59 #define ALL 1
60 #define STAT 2
61 #define PPID 4
62 #define USER 8
63 #define PROG 16
64 #define ARGS 32
65 #define VSZ 64
66 #define RSS 128
67 #define PCPU 256
68 #define ELAPSED 512
69 #define EREG_ARGS 1024
70 /* Different metrics */
71 char *metric_name;
72 enum metric {
73 METRIC_PROCS,
74 METRIC_VSZ,
75 METRIC_RSS,
76 METRIC_CPU,
77 METRIC_ELAPSED
78 };
79 enum metric metric = METRIC_PROCS;
81 int verbose = 0;
82 int uid;
83 pid_t ppid;
84 int vsz;
85 int rss;
86 float pcpu;
87 char *statopts;
88 char *prog;
89 char *args;
90 char *input_filename = NULL;
91 regex_t re_args;
92 char *fmt;
93 char *fails;
94 char tmp[MAX_INPUT_BUFFER];
96 FILE *ps_input = NULL;
99 int
100 main (int argc, char **argv)
101 {
102 char *input_buffer;
103 char *input_line;
104 char *procprog;
106 pid_t mypid = 0;
107 int procuid = 0;
108 pid_t procpid = 0;
109 pid_t procppid = 0;
110 int procvsz = 0;
111 int procrss = 0;
112 int procseconds = 0;
113 float procpcpu = 0;
114 char procstat[8];
115 char procetime[MAX_INPUT_BUFFER] = { '\0' };
116 char *procargs;
118 const char *zombie = "Z";
120 int resultsum = 0; /* bitmask of the filter criteria met by a process */
121 int found = 0; /* counter for number of lines returned in `ps` output */
122 int procs = 0; /* counter for number of processes meeting filter criteria */
123 int pos; /* number of spaces before 'args' in `ps` output */
124 int cols; /* number of columns in ps output */
125 int expected_cols = PS_COLS - 1;
126 int warn = 0; /* number of processes in warn state */
127 int crit = 0; /* number of processes in crit state */
128 int i = 0, j = 0;
129 int result = STATE_UNKNOWN;
130 output chld_out, chld_err;
132 setlocale (LC_ALL, "");
133 bindtextdomain (PACKAGE, LOCALEDIR);
134 textdomain (PACKAGE);
135 setlocale(LC_NUMERIC, "POSIX");
137 input_buffer = malloc (MAX_INPUT_BUFFER);
138 procprog = malloc (MAX_INPUT_BUFFER);
140 asprintf (&metric_name, "PROCS");
141 metric = METRIC_PROCS;
143 /* Parse extra opts if any */
144 argv=np_extra_opts (&argc, argv, progname);
146 if (process_arguments (argc, argv) == ERROR)
147 usage4 (_("Could not parse arguments"));
149 /* get our pid */
150 mypid = getpid();
152 /* Set signal handling and alarm timeout */
153 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
154 die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
155 }
156 (void) alarm ((unsigned) timeout_interval);
158 if (verbose >= 2)
159 printf (_("CMD: %s\n"), PS_COMMAND);
161 if (input_filename == NULL) {
162 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
163 if (chld_err.lines > 0) {
164 printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
165 exit(STATE_WARNING);
166 }
167 } else {
168 result = cmd_file_read( input_filename, &chld_out, 0);
169 }
171 /* flush first line: j starts at 1 */
172 for (j = 1; j < chld_out.lines; j++) {
173 input_line = chld_out.line[j];
175 if (verbose >= 3)
176 printf ("%s", input_line);
178 strcpy (procprog, "");
179 asprintf (&procargs, "%s", "");
181 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
183 /* Zombie processes do not give a procprog command */
184 if ( cols < expected_cols && strstr(procstat, zombie) ) {
185 cols = expected_cols;
186 }
187 if ( cols >= expected_cols ) {
188 resultsum = 0;
189 asprintf (&procargs, "%s", input_line + pos);
190 strip (procargs);
192 /* Some ps return full pathname for command. This removes path */
193 strcpy(procprog, base_name(procprog));
195 /* we need to convert the elapsed time to seconds */
196 procseconds = convert_to_seconds(procetime);
198 if (verbose >= 3)
199 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
200 procs, procuid, procvsz, procrss,
201 procpid, procppid, procpcpu, procstat,
202 procetime, procprog, procargs);
204 /* Ignore self */
205 if (mypid == procpid) continue;
207 if ((options & STAT) && (strstr (statopts, procstat)))
208 resultsum |= STAT;
209 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
210 resultsum |= ARGS;
211 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
212 resultsum |= EREG_ARGS;
213 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
214 resultsum |= PROG;
215 if ((options & PPID) && (procppid == ppid))
216 resultsum |= PPID;
217 if ((options & USER) && (procuid == uid))
218 resultsum |= USER;
219 if ((options & VSZ) && (procvsz >= vsz))
220 resultsum |= VSZ;
221 if ((options & RSS) && (procrss >= rss))
222 resultsum |= RSS;
223 if ((options & PCPU) && (procpcpu >= pcpu))
224 resultsum |= PCPU;
226 found++;
228 /* Next line if filters not matched */
229 if (!(options == resultsum || options == ALL))
230 continue;
232 procs++;
233 if (verbose >= 2) {
234 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
235 procuid, procvsz, procrss,
236 procpid, procppid, procpcpu, procstat,
237 procetime, procprog, procargs);
238 }
240 if (metric == METRIC_VSZ)
241 i = check_thresholds (procvsz);
242 else if (metric == METRIC_RSS)
243 i = check_thresholds (procrss);
244 /* TODO? float thresholds for --metric=CPU */
245 else if (metric == METRIC_CPU)
246 i = check_thresholds ((int)procpcpu);
247 else if (metric == METRIC_ELAPSED)
248 i = check_thresholds (procseconds);
250 if (metric != METRIC_PROCS) {
251 if (i == STATE_WARNING) {
252 warn++;
253 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
254 result = max_state (result, i);
255 }
256 if (i == STATE_CRITICAL) {
257 crit++;
258 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
259 result = max_state (result, i);
260 }
261 }
262 }
263 /* This should not happen */
264 else if (verbose) {
265 printf(_("Not parseable: %s"), input_buffer);
266 }
267 }
269 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
270 printf (_("Unable to read output\n"));
271 return STATE_UNKNOWN;
272 }
274 if ( result == STATE_UNKNOWN )
275 result = STATE_OK;
277 /* Needed if procs found, but none match filter */
278 if ( metric == METRIC_PROCS ) {
279 result = max_state (result, check_thresholds (procs) );
280 }
282 if ( result == STATE_OK ) {
283 printf ("%s %s: ", metric_name, _("OK"));
284 } else if (result == STATE_WARNING) {
285 printf ("%s %s: ", metric_name, _("WARNING"));
286 if ( metric != METRIC_PROCS ) {
287 printf (_("%d warn out of "), warn);
288 }
289 } else if (result == STATE_CRITICAL) {
290 printf ("%s %s: ", metric_name, _("CRITICAL"));
291 if (metric != METRIC_PROCS) {
292 printf (_("%d crit, %d warn out of "), crit, warn);
293 }
294 }
295 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
297 if (strcmp(fmt,"") != 0) {
298 printf (_(" with %s"), fmt);
299 }
301 if ( verbose >= 1 && strcmp(fails,"") )
302 printf (" [%s]", fails);
304 printf ("\n");
305 return result;
306 }
310 /* process command-line arguments */
311 int
312 process_arguments (int argc, char **argv)
313 {
314 int c = 1;
315 char *user;
316 struct passwd *pw;
317 int option = 0;
318 int err;
319 int cflags = REG_NOSUB | REG_EXTENDED;
320 char errbuf[MAX_INPUT_BUFFER];
321 char *temp_string;
322 int i=0;
323 static struct option longopts[] = {
324 {"warning", required_argument, 0, 'w'},
325 {"critical", required_argument, 0, 'c'},
326 {"metric", required_argument, 0, 'm'},
327 {"timeout", required_argument, 0, 't'},
328 {"status", required_argument, 0, 's'},
329 {"ppid", required_argument, 0, 'p'},
330 {"command", required_argument, 0, 'C'},
331 {"vsz", required_argument, 0, 'z'},
332 {"rss", required_argument, 0, 'r'},
333 {"pcpu", required_argument, 0, 'P'},
334 {"elapsed", required_argument, 0, 'e'},
335 {"argument-array", required_argument, 0, 'a'},
336 {"help", no_argument, 0, 'h'},
337 {"version", no_argument, 0, 'V'},
338 {"verbose", no_argument, 0, 'v'},
339 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
340 {"input-file", required_argument, 0, CHAR_MAX+2},
341 {0, 0, 0, 0}
342 };
344 for (c = 1; c < argc; c++)
345 if (strcmp ("-to", argv[c]) == 0)
346 strcpy (argv[c], "-t");
348 while (1) {
349 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
350 longopts, &option);
352 if (c == -1 || c == EOF)
353 break;
355 switch (c) {
356 case '?': /* help */
357 usage5 ();
358 case 'h': /* help */
359 print_help ();
360 exit (STATE_OK);
361 case 'V': /* version */
362 print_revision (progname, NP_VERSION);
363 exit (STATE_OK);
364 case 't': /* timeout period */
365 if (!is_integer (optarg))
366 usage2 (_("Timeout interval must be a positive integer"), optarg);
367 else
368 timeout_interval = atoi (optarg);
369 break;
370 case 'c': /* critical threshold */
371 if (is_integer (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;
382 case 'w': /* warning threshold */
383 if (is_integer (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;
394 case 'p': /* process id */
395 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
396 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
397 options |= PPID;
398 break;
399 }
400 usage4 (_("Parent Process ID must be an integer!"));
401 case 's': /* status */
402 if (statopts)
403 break;
404 else
405 statopts = optarg;
406 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
407 options |= STAT;
408 break;
409 case 'u': /* user or user id */
410 if (is_integer (optarg)) {
411 uid = atoi (optarg);
412 pw = getpwuid ((uid_t) uid);
413 /* check to be sure user exists */
414 if (pw == NULL)
415 usage2 (_("UID was not found"), optarg);
416 }
417 else {
418 pw = getpwnam (optarg);
419 /* check to be sure user exists */
420 if (pw == NULL)
421 usage2 (_("User name was not found"), optarg);
422 /* then get uid */
423 uid = pw->pw_uid;
424 }
425 user = pw->pw_name;
426 asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
427 uid, user);
428 options |= USER;
429 break;
430 case 'C': /* command */
431 /* TODO: allow this to be passed in with --metric */
432 if (prog)
433 break;
434 else
435 prog = optarg;
436 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
437 prog);
438 options |= PROG;
439 break;
440 case 'a': /* args (full path name with args) */
441 /* TODO: allow this to be passed in with --metric */
442 if (args)
443 break;
444 else
445 args = optarg;
446 asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
447 options |= ARGS;
448 break;
449 case CHAR_MAX+1:
450 err = regcomp(&re_args, optarg, cflags);
451 if (err != 0) {
452 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
453 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
454 }
455 /* Strip off any | within the regex optarg */
456 temp_string = strdup(optarg);
457 while(temp_string[i]!='\0'){
458 if(temp_string[i]=='|')
459 temp_string[i]=',';
460 i++;
461 }
462 asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
463 options |= EREG_ARGS;
464 break;
465 case 'r': /* RSS */
466 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
467 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
468 options |= RSS;
469 break;
470 }
471 usage4 (_("RSS must be an integer!"));
472 case 'z': /* VSZ */
473 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
474 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
475 options |= VSZ;
476 break;
477 }
478 usage4 (_("VSZ must be an integer!"));
479 case 'P': /* PCPU */
480 /* TODO: -P 1.5.5 is accepted */
481 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
482 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
483 options |= PCPU;
484 break;
485 }
486 usage4 (_("PCPU must be a float!"));
487 case 'm':
488 asprintf (&metric_name, "%s", optarg);
489 if ( strcmp(optarg, "PROCS") == 0) {
490 metric = METRIC_PROCS;
491 break;
492 }
493 else if ( strcmp(optarg, "VSZ") == 0) {
494 metric = METRIC_VSZ;
495 break;
496 }
497 else if ( strcmp(optarg, "RSS") == 0 ) {
498 metric = METRIC_RSS;
499 break;
500 }
501 else if ( strcmp(optarg, "CPU") == 0 ) {
502 metric = METRIC_CPU;
503 break;
504 }
505 else if ( strcmp(optarg, "ELAPSED") == 0) {
506 metric = METRIC_ELAPSED;
507 break;
508 }
510 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
511 case 'v': /* command */
512 verbose++;
513 break;
514 case CHAR_MAX+2:
515 input_filename = optarg;
516 break;
517 }
518 }
520 c = optind;
521 if (wmax == -1 && argv[c])
522 wmax = atoi (argv[c++]);
523 if (cmax == -1 && argv[c])
524 cmax = atoi (argv[c++]);
525 if (statopts == NULL && argv[c]) {
526 asprintf (&statopts, "%s", argv[c++]);
527 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
528 options |= STAT;
529 }
531 return validate_arguments ();
532 }
536 int
537 validate_arguments ()
538 {
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 }
555 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
556 /* printf ("At least one threshold must be set\n"); */
557 /* return ERROR; */
558 /* } */
560 if (options == 0)
561 options = ALL;
563 if (statopts==NULL)
564 statopts = strdup("");
566 if (prog==NULL)
567 prog = strdup("");
569 if (args==NULL)
570 args = strdup("");
572 if (fmt==NULL)
573 fmt = strdup("");
575 if (fails==NULL)
576 fails = strdup("");
578 return options;
579 }
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 }
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 }
616 /* convert the elapsed time to seconds */
617 int
618 convert_to_seconds(char *etime) {
620 char *ptr;
621 int total;
623 int hyphcnt;
624 int coloncnt;
625 int days;
626 int hours;
627 int minutes;
628 int seconds;
630 hyphcnt = 0;
631 coloncnt = 0;
632 days = 0;
633 hours = 0;
634 minutes = 0;
635 seconds = 0;
637 for (ptr = etime; *ptr != '\0'; ptr++) {
639 if (*ptr == '-') {
640 hyphcnt++;
641 continue;
642 }
643 if (*ptr == ':') {
644 coloncnt++;
645 continue;
646 }
647 }
649 if (hyphcnt > 0) {
650 sscanf(etime, "%d-%d:%d:%d",
651 &days, &hours, &minutes, &seconds);
652 /* linux 2.6.5/2.6.6 reporting some processes with infinite
653 * elapsed times for some reason */
654 if (days == 49710) {
655 return 0;
656 }
657 } else {
658 if (coloncnt == 2) {
659 sscanf(etime, "%d:%d:%d",
660 &hours, &minutes, &seconds);
661 } else if (coloncnt == 1) {
662 sscanf(etime, "%d:%d",
663 &minutes, &seconds);
664 }
665 }
667 total = (days * 86400) +
668 (hours * 3600) +
669 (minutes * 60) +
670 seconds;
672 if (verbose >= 3 && metric == METRIC_ELAPSED) {
673 printf("seconds: %d\n", total);
674 }
675 return total;
676 }
679 void
680 print_help (void)
681 {
682 print_revision (progname, NP_VERSION);
684 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
685 printf (COPYRIGHT, copyright, email);
687 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
688 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
689 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
691 printf ("\n\n");
693 print_usage ();
695 printf (UT_HELP_VRSN);
696 printf (UT_EXTRA_OPTS);
697 printf (" %s\n", "-w, --warning=RANGE");
698 printf (" %s\n", _("Generate warning state if metric is outside this range"));
699 printf (" %s\n", "-c, --critical=RANGE");
700 printf (" %s\n", _("Generate critical state if metric is outside this range"));
701 printf (" %s\n", "-m, --metric=TYPE");
702 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
703 printf (" %s\n", _("PROCS - number of processes (default)"));
704 printf (" %s\n", _("VSZ - virtual memory size"));
705 printf (" %s\n", _("RSS - resident set memory size"));
706 printf (" %s\n", _("CPU - percentage CPU"));
707 /* only linux etime is support currently */
708 #if defined( __linux__ )
709 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
710 #endif /* defined(__linux__) */
711 printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
713 printf (" %s\n", "-v, --verbose");
714 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
716 printf ("\n");
717 printf ("%s\n", "Filters:");
718 printf (" %s\n", "-s, --state=STATUSFLAGS");
719 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
720 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
721 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
722 printf (" %s\n", "-p, --ppid=PPID");
723 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
724 printf (" %s\n", "-z, --vsz=VSZ");
725 printf (" %s\n", _("Only scan for processes with VSZ higher than indicated."));
726 printf (" %s\n", "-r, --rss=RSS");
727 printf (" %s\n", _("Only scan for processes with RSS higher than indicated."));
728 printf (" %s\n", "-P, --pcpu=PCPU");
729 printf (" %s\n", _("Only scan for processes with PCPU higher than indicated."));
730 printf (" %s\n", "-u, --user=USER");
731 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
732 printf (" %s\n", "-a, --argument-array=STRING");
733 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
734 printf (" %s\n", "--ereg-argument-array=STRING");
735 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
736 printf (" %s\n", "-C, --command=COMMAND");
737 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
739 printf(_("\n\
740 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
741 specified 'max:min', a warning status will be generated if the\n\
742 count is inside the specified range\n\n"));
744 printf(_("\
745 This plugin checks the number of currently running processes and\n\
746 generates WARNING or CRITICAL states if the process count is outside\n\
747 the specified threshold ranges. The process count can be filtered by\n\
748 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
749 be the total number of running processes\n\n"));
751 printf ("%s\n", _("Examples:"));
752 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
753 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
754 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
755 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
756 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
757 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
758 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
759 printf (" %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
760 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
761 printf (" %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
763 printf (UT_SUPPORT);
764 }
766 void
767 print_usage (void)
768 {
769 printf ("%s\n", _("Usage:"));
770 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");
772 printf (" [-C command] [-t timeout] [-v]\n");
773 }