1 /*****************************************************************************
2 *
3 * Nagios check_procs plugin
4 *
5 * License: GPL
6 * Copyright (c) 2000-2008 Nagios Plugins Development Team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_procs plugin
13 *
14 * Checks all processes and generates WARNING or CRITICAL states if the
15 * specified metric is outside the required threshold ranges. The metric
16 * defaults to number of processes. Search filters can be applied to limit
17 * the processes to check.
18 *
19 *
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24 *
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 *
30 * You should have received a copy of the GNU General Public License
31 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 *
33 * $Id$
34 *
35 *****************************************************************************/
37 const char *progname = "check_procs";
38 const char *program_name = "check_procs"; /* Required for coreutils libs */
39 const char *revision = "$Revision$";
40 const char *copyright = "2000-2008";
41 const char *email = "nagiosplug-devel@lists.sourceforge.net";
43 #include "common.h"
44 #include "popen.h"
45 #include "utils.h"
46 #include "regex.h"
48 #include <pwd.h>
50 int process_arguments (int, char **);
51 int validate_arguments (void);
52 int check_thresholds (int);
53 int convert_to_seconds (char *);
54 void print_help (void);
55 void print_usage (void);
57 int wmax = -1;
58 int cmax = -1;
59 int wmin = -1;
60 int cmin = -1;
62 int options = 0; /* bitmask of filter criteria to test against */
63 #define ALL 1
64 #define STAT 2
65 #define PPID 4
66 #define USER 8
67 #define PROG 16
68 #define ARGS 32
69 #define VSZ 64
70 #define RSS 128
71 #define PCPU 256
72 #define ELAPSED 512
73 #define EREG_ARGS 1024
74 /* Different metrics */
75 char *metric_name;
76 enum metric {
77 METRIC_PROCS,
78 METRIC_VSZ,
79 METRIC_RSS,
80 METRIC_CPU,
81 METRIC_ELAPSED
82 };
83 enum metric metric = METRIC_PROCS;
85 int verbose = 0;
86 int uid;
87 pid_t ppid;
88 int vsz;
89 int rss;
90 float pcpu;
91 char *statopts;
92 char *prog;
93 char *args;
94 regex_t re_args;
95 char *fmt;
96 char *fails;
97 char tmp[MAX_INPUT_BUFFER];
101 int
102 main (int argc, char **argv)
103 {
104 char *input_buffer;
105 char *input_line;
106 char *procprog;
108 pid_t mypid = 0;
109 int procuid = 0;
110 pid_t procpid = 0;
111 pid_t procppid = 0;
112 int procvsz = 0;
113 int procrss = 0;
114 int procseconds = 0;
115 float procpcpu = 0;
116 char procstat[8];
117 char procetime[MAX_INPUT_BUFFER] = { '\0' };
118 char *procargs;
120 const char *zombie = "Z";
122 int resultsum = 0; /* bitmask of the filter criteria met by a process */
123 int found = 0; /* counter for number of lines returned in `ps` output */
124 int procs = 0; /* counter for number of processes meeting filter criteria */
125 int pos; /* number of spaces before 'args' in `ps` output */
126 int cols; /* number of columns in ps output */
127 int expected_cols = PS_COLS - 1;
128 int warn = 0; /* number of processes in warn state */
129 int crit = 0; /* number of processes in crit state */
130 int i = 0;
131 int result = STATE_UNKNOWN;
133 setlocale (LC_ALL, "");
134 bindtextdomain (PACKAGE, LOCALEDIR);
135 textdomain (PACKAGE);
136 setlocale(LC_NUMERIC, "POSIX");
138 input_buffer = malloc (MAX_INPUT_BUFFER);
139 procprog = malloc (MAX_INPUT_BUFFER);
141 asprintf (&metric_name, "PROCS");
142 metric = METRIC_PROCS;
144 if (process_arguments (argc, argv) == ERROR)
145 usage4 (_("Could not parse arguments"));
147 /* get our pid */
148 mypid = getpid();
150 /* Set signal handling and alarm timeout */
151 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
152 usage4 (_("Cannot catch SIGALRM"));
153 }
154 alarm (timeout_interval);
156 if (verbose >= 2)
157 printf (_("CMD: %s\n"), PS_COMMAND);
159 child_process = spopen (PS_COMMAND);
160 if (child_process == NULL) {
161 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
162 return STATE_UNKNOWN;
163 }
165 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
166 if (child_stderr == NULL)
167 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
169 /* flush first line */
170 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
171 while ( input_buffer[strlen(input_buffer)-1] != '\n' )
172 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
174 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
175 asprintf (&input_line, "%s", input_buffer);
176 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
177 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
178 asprintf (&input_line, "%s%s", input_line, input_buffer);
179 }
181 if (verbose >= 3)
182 printf ("%s", input_line);
184 strcpy (procprog, "");
185 asprintf (&procargs, "%s", "");
187 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
189 /* Zombie processes do not give a procprog command */
190 if ( cols < expected_cols && strstr(procstat, zombie) ) {
191 cols = expected_cols;
192 }
193 if ( cols >= expected_cols ) {
194 resultsum = 0;
195 asprintf (&procargs, "%s", input_line + pos);
196 strip (procargs);
198 /* Some ps return full pathname for command. This removes path */
199 strcpy(procprog, base_name(procprog));
201 /* we need to convert the elapsed time to seconds */
202 procseconds = convert_to_seconds(procetime);
204 if (verbose >= 3)
205 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
206 procs, procuid, procvsz, procrss,
207 procpid, procppid, procpcpu, procstat,
208 procetime, procprog, procargs);
210 /* Ignore self */
211 if (mypid == procpid) continue;
213 if ((options & STAT) && (strstr (statopts, procstat)))
214 resultsum |= STAT;
215 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
216 resultsum |= ARGS;
217 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
218 resultsum |= EREG_ARGS;
219 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
220 resultsum |= PROG;
221 if ((options & PPID) && (procppid == ppid))
222 resultsum |= PPID;
223 if ((options & USER) && (procuid == uid))
224 resultsum |= USER;
225 if ((options & VSZ) && (procvsz >= vsz))
226 resultsum |= VSZ;
227 if ((options & RSS) && (procrss >= rss))
228 resultsum |= RSS;
229 if ((options & PCPU) && (procpcpu >= pcpu))
230 resultsum |= PCPU;
232 found++;
234 /* Next line if filters not matched */
235 if (!(options == resultsum || options == ALL))
236 continue;
238 procs++;
239 if (verbose >= 2) {
240 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
241 procuid, procvsz, procrss,
242 procpid, procppid, procpcpu, procstat,
243 procetime, procprog, procargs);
244 }
246 if (metric == METRIC_VSZ)
247 i = check_thresholds (procvsz);
248 else if (metric == METRIC_RSS)
249 i = check_thresholds (procrss);
250 /* TODO? float thresholds for --metric=CPU */
251 else if (metric == METRIC_CPU)
252 i = check_thresholds ((int)procpcpu);
253 else if (metric == METRIC_ELAPSED)
254 i = check_thresholds (procseconds);
256 if (metric != METRIC_PROCS) {
257 if (i == STATE_WARNING) {
258 warn++;
259 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
260 result = max_state (result, i);
261 }
262 if (i == STATE_CRITICAL) {
263 crit++;
264 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
265 result = max_state (result, i);
266 }
267 }
268 }
269 /* This should not happen */
270 else if (verbose) {
271 printf(_("Not parseable: %s"), input_buffer);
272 }
273 }
275 /* If we get anything on STDERR, at least set warning */
276 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
277 if (verbose)
278 printf ("STDERR: %s", input_buffer);
279 result = max_state (result, STATE_WARNING);
280 printf (_("System call sent warnings to stderr\n"));
281 }
283 (void) fclose (child_stderr);
285 /* close the pipe */
286 if (spclose (child_process)) {
287 printf (_("System call returned nonzero status\n"));
288 result = max_state (result, STATE_WARNING);
289 }
291 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
292 printf (_("Unable to read output\n"));
293 return result;
294 }
296 if ( result == STATE_UNKNOWN )
297 result = STATE_OK;
299 /* Needed if procs found, but none match filter */
300 if ( metric == METRIC_PROCS ) {
301 result = max_state (result, check_thresholds (procs) );
302 }
304 if ( result == STATE_OK ) {
305 printf ("%s %s: ", metric_name, _("OK"));
306 } else if (result == STATE_WARNING) {
307 printf ("%s %s: ", metric_name, _("WARNING"));
308 if ( metric != METRIC_PROCS ) {
309 printf (_("%d warn out of "), warn);
310 }
311 } else if (result == STATE_CRITICAL) {
312 printf ("%s %s: ", metric_name, _("CRITICAL"));
313 if (metric != METRIC_PROCS) {
314 printf (_("%d crit, %d warn out of "), crit, warn);
315 }
316 }
317 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
319 if (strcmp(fmt,"") != 0) {
320 printf (_(" with %s"), fmt);
321 }
323 if ( verbose >= 1 && strcmp(fails,"") )
324 printf (" [%s]", fails);
326 printf ("\n");
327 return result;
328 }
332 /* process command-line arguments */
333 int
334 process_arguments (int argc, char **argv)
335 {
336 int c = 1;
337 char *user;
338 struct passwd *pw;
339 int option = 0;
340 int err;
341 int cflags = REG_NOSUB | REG_EXTENDED;
342 char errbuf[MAX_INPUT_BUFFER];
343 static struct option longopts[] = {
344 {"warning", required_argument, 0, 'w'},
345 {"critical", required_argument, 0, 'c'},
346 {"metric", required_argument, 0, 'm'},
347 {"timeout", required_argument, 0, 't'},
348 {"status", required_argument, 0, 's'},
349 {"ppid", required_argument, 0, 'p'},
350 {"command", required_argument, 0, 'C'},
351 {"vsz", required_argument, 0, 'z'},
352 {"rss", required_argument, 0, 'r'},
353 {"pcpu", required_argument, 0, 'P'},
354 {"elapsed", required_argument, 0, 'e'},
355 {"argument-array", required_argument, 0, 'a'},
356 {"help", no_argument, 0, 'h'},
357 {"version", no_argument, 0, 'V'},
358 {"verbose", no_argument, 0, 'v'},
359 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
360 {0, 0, 0, 0}
361 };
363 for (c = 1; c < argc; c++)
364 if (strcmp ("-to", argv[c]) == 0)
365 strcpy (argv[c], "-t");
367 while (1) {
368 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
369 longopts, &option);
371 if (c == -1 || c == EOF)
372 break;
374 switch (c) {
375 case '?': /* help */
376 usage5 ();
377 case 'h': /* help */
378 print_help ();
379 exit (STATE_OK);
380 case 'V': /* version */
381 print_revision (progname, revision);
382 exit (STATE_OK);
383 case 't': /* timeout period */
384 if (!is_integer (optarg))
385 usage2 (_("Timeout interval must be a positive integer"), optarg);
386 else
387 timeout_interval = atoi (optarg);
388 break;
389 case 'c': /* critical threshold */
390 if (is_integer (optarg))
391 cmax = atoi (optarg);
392 else if (sscanf (optarg, ":%d", &cmax) == 1)
393 break;
394 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
395 break;
396 else if (sscanf (optarg, "%d:", &cmin) == 1)
397 break;
398 else
399 usage4 (_("Critical Process Count must be an integer!"));
400 break;
401 case 'w': /* warning threshold */
402 if (is_integer (optarg))
403 wmax = atoi (optarg);
404 else if (sscanf (optarg, ":%d", &wmax) == 1)
405 break;
406 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
407 break;
408 else if (sscanf (optarg, "%d:", &wmin) == 1)
409 break;
410 else
411 usage4 (_("Warning Process Count must be an integer!"));
412 break;
413 case 'p': /* process id */
414 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
415 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
416 options |= PPID;
417 break;
418 }
419 usage4 (_("Parent Process ID must be an integer!"));
420 case 's': /* status */
421 if (statopts)
422 break;
423 else
424 statopts = optarg;
425 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
426 options |= STAT;
427 break;
428 case 'u': /* user or user id */
429 if (is_integer (optarg)) {
430 uid = atoi (optarg);
431 pw = getpwuid ((uid_t) uid);
432 /* check to be sure user exists */
433 if (pw == NULL)
434 usage2 (_("UID was not found"), optarg);
435 }
436 else {
437 pw = getpwnam (optarg);
438 /* check to be sure user exists */
439 if (pw == NULL)
440 usage2 (_("User name was not found"), optarg);
441 /* then get uid */
442 uid = pw->pw_uid;
443 }
444 user = pw->pw_name;
445 asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
446 uid, user);
447 options |= USER;
448 break;
449 case 'C': /* command */
450 /* TODO: allow this to be passed in with --metric */
451 if (prog)
452 break;
453 else
454 prog = optarg;
455 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
456 prog);
457 options |= PROG;
458 break;
459 case 'a': /* args (full path name with args) */
460 /* TODO: allow this to be passed in with --metric */
461 if (args)
462 break;
463 else
464 args = optarg;
465 asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
466 options |= ARGS;
467 break;
468 case CHAR_MAX+1:
469 err = regcomp(&re_args, optarg, cflags);
470 if (err != 0) {
471 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
472 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
473 }
474 asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
475 options |= EREG_ARGS;
476 break;
477 case 'r': /* RSS */
478 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
479 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
480 options |= RSS;
481 break;
482 }
483 usage4 (_("RSS must be an integer!"));
484 case 'z': /* VSZ */
485 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
486 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
487 options |= VSZ;
488 break;
489 }
490 usage4 (_("VSZ must be an integer!"));
491 case 'P': /* PCPU */
492 /* TODO: -P 1.5.5 is accepted */
493 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
494 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
495 options |= PCPU;
496 break;
497 }
498 usage4 (_("PCPU must be a float!"));
499 case 'm':
500 asprintf (&metric_name, "%s", optarg);
501 if ( strcmp(optarg, "PROCS") == 0) {
502 metric = METRIC_PROCS;
503 break;
504 }
505 else if ( strcmp(optarg, "VSZ") == 0) {
506 metric = METRIC_VSZ;
507 break;
508 }
509 else if ( strcmp(optarg, "RSS") == 0 ) {
510 metric = METRIC_RSS;
511 break;
512 }
513 else if ( strcmp(optarg, "CPU") == 0 ) {
514 metric = METRIC_CPU;
515 break;
516 }
517 else if ( strcmp(optarg, "ELAPSED") == 0) {
518 metric = METRIC_ELAPSED;
519 break;
520 }
522 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
523 case 'v': /* command */
524 verbose++;
525 break;
526 }
527 }
529 c = optind;
530 if (wmax == -1 && argv[c])
531 wmax = atoi (argv[c++]);
532 if (cmax == -1 && argv[c])
533 cmax = atoi (argv[c++]);
534 if (statopts == NULL && argv[c]) {
535 asprintf (&statopts, "%s", argv[c++]);
536 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
537 options |= STAT;
538 }
540 return validate_arguments ();
541 }
545 int
546 validate_arguments ()
547 {
549 if (wmax >= 0 && wmin == -1)
550 wmin = 0;
551 if (cmax >= 0 && cmin == -1)
552 cmin = 0;
553 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
554 if (wmax > cmax && cmax != -1) {
555 printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
556 return ERROR;
557 }
558 if (cmin > wmin && wmin != -1) {
559 printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
560 return ERROR;
561 }
562 }
564 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
565 /* printf ("At least one threshold must be set\n"); */
566 /* return ERROR; */
567 /* } */
569 if (options == 0)
570 options = ALL;
572 if (statopts==NULL)
573 statopts = strdup("");
575 if (prog==NULL)
576 prog = strdup("");
578 if (args==NULL)
579 args = strdup("");
581 if (fmt==NULL)
582 fmt = strdup("");
584 if (fails==NULL)
585 fails = strdup("");
587 return options;
588 }
592 /* Check thresholds against value */
593 int
594 check_thresholds (int value)
595 {
596 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
597 return OK;
598 }
599 else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
600 if (value > cmax && value < cmin)
601 return STATE_CRITICAL;
602 }
603 else if (cmax >= 0 && value > cmax) {
604 return STATE_CRITICAL;
605 }
606 else if (cmin >= 0 && value < cmin) {
607 return STATE_CRITICAL;
608 }
610 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
611 if (value > wmax && value < wmin) {
612 return STATE_WARNING;
613 }
614 }
615 else if (wmax >= 0 && value > wmax) {
616 return STATE_WARNING;
617 }
618 else if (wmin >= 0 && value < wmin) {
619 return STATE_WARNING;
620 }
621 return STATE_OK;
622 }
625 /* convert the elapsed time to seconds */
626 int
627 convert_to_seconds(char *etime) {
629 char *ptr;
630 int total;
632 int hyphcnt;
633 int coloncnt;
634 int days;
635 int hours;
636 int minutes;
637 int seconds;
639 hyphcnt = 0;
640 coloncnt = 0;
641 days = 0;
642 hours = 0;
643 minutes = 0;
644 seconds = 0;
646 for (ptr = etime; *ptr != '\0'; ptr++) {
648 if (*ptr == '-') {
649 hyphcnt++;
650 continue;
651 }
652 if (*ptr == ':') {
653 coloncnt++;
654 continue;
655 }
656 }
658 if (hyphcnt > 0) {
659 sscanf(etime, "%d-%d:%d:%d",
660 &days, &hours, &minutes, &seconds);
661 /* linux 2.6.5/2.6.6 reporting some processes with infinite
662 * elapsed times for some reason */
663 if (days == 49710) {
664 return 0;
665 }
666 } else {
667 if (coloncnt == 2) {
668 sscanf(etime, "%d:%d:%d",
669 &hours, &minutes, &seconds);
670 } else if (coloncnt == 1) {
671 sscanf(etime, "%d:%d",
672 &minutes, &seconds);
673 }
674 }
676 total = (days * 86400) +
677 (hours * 3600) +
678 (minutes * 60) +
679 seconds;
681 if (verbose >= 3 && metric == METRIC_ELAPSED) {
682 printf("seconds: %d\n", total);
683 }
684 return total;
685 }
688 void
689 print_help (void)
690 {
691 print_revision (progname, revision);
693 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
694 printf (COPYRIGHT, copyright, email);
696 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
697 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
698 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
700 printf ("\n\n");
702 print_usage ();
704 printf ("%s\n", _("Required Arguments:"));
705 printf (" %s\n", "-w, --warning=RANGE");
706 printf (" %s\n", _("Generate warning state if metric is outside this range"));
707 printf (" %s\n", "-c, --critical=RANGE");
708 printf (" %s\n", _("Generate critical state if metric is outside this range"));
710 printf ("%s\n", _("Optional Arguments:"));
711 printf (" %s\n", "-m, --metric=TYPE");
712 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
713 printf (" %s\n", _("PROCS - number of processes (default)"));
714 printf (" %s\n", _("VSZ - virtual memory size"));
715 printf (" %s\n", _("RSS - resident set memory size"));
716 printf (" %s\n", _("CPU - percentage cpu"));
717 /* only linux etime is support currently */
718 #if defined( __linux__ )
719 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
720 #endif /* defined(__linux__) */
721 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
723 printf (" %s\n", "-v, --verbose");
724 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
726 printf ("%s\n", "Optional Filters:");
727 printf (" %s\n", "-s, --state=STATUSFLAGS");
728 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
729 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
730 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
731 printf (" %s\n", "-p, --ppid=PPID");
732 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
733 printf (" %s\n", "-z, --vsz=VSZ");
734 printf (" %s\n", _("Only scan for processes with vsz higher than indicated."));
735 printf (" %s\n", "-r, --rss=RSS");
736 printf (" %s\n", _("Only scan for processes with rss higher than indicated."));
737 printf (" %s\n", "-P, --pcpu=PCPU");
738 printf (" %s\n", _("Only scan for processes with pcpu higher than indicated."));
739 printf (" %s\n", "-u, --user=USER");
740 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
741 printf (" %s\n", "-a, --argument-array=STRING");
742 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
743 printf (" %s\n", "--ereg-argument-array=STRING");
744 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
745 printf (" %s\n", "-C, --command=COMMAND");
746 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
748 printf(_("\n\
749 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
750 specified 'max:min', a warning status will be generated if the\n\
751 count is inside the specified range\n\n"));
753 printf(_("\
754 This plugin checks the number of currently running processes and\n\
755 generates WARNING or CRITICAL states if the process count is outside\n\
756 the specified threshold ranges. The process count can be filtered by\n\
757 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
758 be the total number of running processes\n\n"));
760 printf ("%s\n", _("Examples:"));
761 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
762 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
763 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
764 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
765 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
766 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
767 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
768 printf (" %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
769 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
770 printf (" %s\n\n", _("Alert if cpu of any processes over 10%% or 20%%"));
772 printf (_(UT_SUPPORT));
773 }
775 void
776 print_usage (void)
777 {
778 printf (_("Usage: "));
779 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
780 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
781 printf (" [-C command] [-t timeout] [-v]\n");
782 }