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 "utils.h"
45 #include "utils_cmd.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 char *input_filename = NULL;
95 regex_t re_args;
96 char *fmt;
97 char *fails;
98 char tmp[MAX_INPUT_BUFFER];
100 FILE *ps_input = NULL;
103 int
104 main (int argc, char **argv)
105 {
106 char *input_buffer;
107 char *input_line;
108 char *procprog;
110 pid_t mypid = 0;
111 int procuid = 0;
112 pid_t procpid = 0;
113 pid_t procppid = 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 asprintf (&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"));
159 }
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);
170 }
171 } else {
172 result = cmd_file_read( input_filename, &chld_out, 0);
173 }
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 asprintf (&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;
190 }
191 if ( cols >= expected_cols ) {
192 resultsum = 0;
193 asprintf (&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 if ((options & STAT) && (strstr (statopts, procstat)))
212 resultsum |= STAT;
213 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
214 resultsum |= ARGS;
215 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
216 resultsum |= EREG_ARGS;
217 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
218 resultsum |= PROG;
219 if ((options & PPID) && (procppid == ppid))
220 resultsum |= PPID;
221 if ((options & USER) && (procuid == uid))
222 resultsum |= USER;
223 if ((options & VSZ) && (procvsz >= vsz))
224 resultsum |= VSZ;
225 if ((options & RSS) && (procrss >= rss))
226 resultsum |= RSS;
227 if ((options & PCPU) && (procpcpu >= pcpu))
228 resultsum |= PCPU;
230 found++;
232 /* Next line if filters not matched */
233 if (!(options == resultsum || options == ALL))
234 continue;
236 procs++;
237 if (verbose >= 2) {
238 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
239 procuid, procvsz, procrss,
240 procpid, procppid, procpcpu, procstat,
241 procetime, procprog, procargs);
242 }
244 if (metric == METRIC_VSZ)
245 i = check_thresholds (procvsz);
246 else if (metric == METRIC_RSS)
247 i = check_thresholds (procrss);
248 /* TODO? float thresholds for --metric=CPU */
249 else if (metric == METRIC_CPU)
250 i = check_thresholds ((int)procpcpu);
251 else if (metric == METRIC_ELAPSED)
252 i = check_thresholds (procseconds);
254 if (metric != METRIC_PROCS) {
255 if (i == STATE_WARNING) {
256 warn++;
257 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
258 result = max_state (result, i);
259 }
260 if (i == STATE_CRITICAL) {
261 crit++;
262 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
263 result = max_state (result, i);
264 }
265 }
266 }
267 /* This should not happen */
268 else if (verbose) {
269 printf(_("Not parseable: %s"), input_buffer);
270 }
271 }
273 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
274 printf (_("Unable to read output\n"));
275 return STATE_UNKNOWN;
276 }
278 if ( result == STATE_UNKNOWN )
279 result = STATE_OK;
281 /* Needed if procs found, but none match filter */
282 if ( metric == METRIC_PROCS ) {
283 result = max_state (result, check_thresholds (procs) );
284 }
286 if ( result == STATE_OK ) {
287 printf ("%s %s: ", metric_name, _("OK"));
288 } else if (result == STATE_WARNING) {
289 printf ("%s %s: ", metric_name, _("WARNING"));
290 if ( metric != METRIC_PROCS ) {
291 printf (_("%d warn out of "), warn);
292 }
293 } else if (result == STATE_CRITICAL) {
294 printf ("%s %s: ", metric_name, _("CRITICAL"));
295 if (metric != METRIC_PROCS) {
296 printf (_("%d crit, %d warn out of "), crit, warn);
297 }
298 }
299 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
301 if (strcmp(fmt,"") != 0) {
302 printf (_(" with %s"), fmt);
303 }
305 if ( verbose >= 1 && strcmp(fails,"") )
306 printf (" [%s]", fails);
308 printf ("\n");
309 return result;
310 }
314 /* process command-line arguments */
315 int
316 process_arguments (int argc, char **argv)
317 {
318 int c = 1;
319 char *user;
320 struct passwd *pw;
321 int option = 0;
322 int err;
323 int cflags = REG_NOSUB | REG_EXTENDED;
324 char errbuf[MAX_INPUT_BUFFER];
325 static struct option longopts[] = {
326 {"warning", required_argument, 0, 'w'},
327 {"critical", required_argument, 0, 'c'},
328 {"metric", required_argument, 0, 'm'},
329 {"timeout", required_argument, 0, 't'},
330 {"status", required_argument, 0, 's'},
331 {"ppid", required_argument, 0, 'p'},
332 {"command", required_argument, 0, 'C'},
333 {"vsz", required_argument, 0, 'z'},
334 {"rss", required_argument, 0, 'r'},
335 {"pcpu", required_argument, 0, 'P'},
336 {"elapsed", required_argument, 0, 'e'},
337 {"argument-array", required_argument, 0, 'a'},
338 {"help", no_argument, 0, 'h'},
339 {"version", no_argument, 0, 'V'},
340 {"verbose", no_argument, 0, 'v'},
341 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
342 {"input-file", required_argument, 0, CHAR_MAX+2},
343 {0, 0, 0, 0}
344 };
346 for (c = 1; c < argc; c++)
347 if (strcmp ("-to", argv[c]) == 0)
348 strcpy (argv[c], "-t");
350 while (1) {
351 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
352 longopts, &option);
354 if (c == -1 || c == EOF)
355 break;
357 switch (c) {
358 case '?': /* help */
359 usage5 ();
360 case 'h': /* help */
361 print_help ();
362 exit (STATE_OK);
363 case 'V': /* version */
364 print_revision (progname, revision);
365 exit (STATE_OK);
366 case 't': /* timeout period */
367 if (!is_integer (optarg))
368 usage2 (_("Timeout interval must be a positive integer"), optarg);
369 else
370 timeout_interval = atoi (optarg);
371 break;
372 case 'c': /* critical threshold */
373 if (is_integer (optarg))
374 cmax = atoi (optarg);
375 else if (sscanf (optarg, ":%d", &cmax) == 1)
376 break;
377 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
378 break;
379 else if (sscanf (optarg, "%d:", &cmin) == 1)
380 break;
381 else
382 usage4 (_("Critical Process Count must be an integer!"));
383 break;
384 case 'w': /* warning threshold */
385 if (is_integer (optarg))
386 wmax = atoi (optarg);
387 else if (sscanf (optarg, ":%d", &wmax) == 1)
388 break;
389 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
390 break;
391 else if (sscanf (optarg, "%d:", &wmin) == 1)
392 break;
393 else
394 usage4 (_("Warning Process Count must be an integer!"));
395 break;
396 case 'p': /* process id */
397 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
398 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
399 options |= PPID;
400 break;
401 }
402 usage4 (_("Parent Process ID must be an integer!"));
403 case 's': /* status */
404 if (statopts)
405 break;
406 else
407 statopts = optarg;
408 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
409 options |= STAT;
410 break;
411 case 'u': /* user or user id */
412 if (is_integer (optarg)) {
413 uid = atoi (optarg);
414 pw = getpwuid ((uid_t) uid);
415 /* check to be sure user exists */
416 if (pw == NULL)
417 usage2 (_("UID was not found"), optarg);
418 }
419 else {
420 pw = getpwnam (optarg);
421 /* check to be sure user exists */
422 if (pw == NULL)
423 usage2 (_("User name was not found"), optarg);
424 /* then get uid */
425 uid = pw->pw_uid;
426 }
427 user = pw->pw_name;
428 asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
429 uid, user);
430 options |= USER;
431 break;
432 case 'C': /* command */
433 /* TODO: allow this to be passed in with --metric */
434 if (prog)
435 break;
436 else
437 prog = optarg;
438 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
439 prog);
440 options |= PROG;
441 break;
442 case 'a': /* args (full path name with args) */
443 /* TODO: allow this to be passed in with --metric */
444 if (args)
445 break;
446 else
447 args = optarg;
448 asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
449 options |= ARGS;
450 break;
451 case CHAR_MAX+1:
452 err = regcomp(&re_args, optarg, cflags);
453 if (err != 0) {
454 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
455 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
456 }
457 asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
458 options |= EREG_ARGS;
459 break;
460 case 'r': /* RSS */
461 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
462 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
463 options |= RSS;
464 break;
465 }
466 usage4 (_("RSS must be an integer!"));
467 case 'z': /* VSZ */
468 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
469 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
470 options |= VSZ;
471 break;
472 }
473 usage4 (_("VSZ must be an integer!"));
474 case 'P': /* PCPU */
475 /* TODO: -P 1.5.5 is accepted */
476 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
477 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
478 options |= PCPU;
479 break;
480 }
481 usage4 (_("PCPU must be a float!"));
482 case 'm':
483 asprintf (&metric_name, "%s", optarg);
484 if ( strcmp(optarg, "PROCS") == 0) {
485 metric = METRIC_PROCS;
486 break;
487 }
488 else if ( strcmp(optarg, "VSZ") == 0) {
489 metric = METRIC_VSZ;
490 break;
491 }
492 else if ( strcmp(optarg, "RSS") == 0 ) {
493 metric = METRIC_RSS;
494 break;
495 }
496 else if ( strcmp(optarg, "CPU") == 0 ) {
497 metric = METRIC_CPU;
498 break;
499 }
500 else if ( strcmp(optarg, "ELAPSED") == 0) {
501 metric = METRIC_ELAPSED;
502 break;
503 }
505 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
506 case 'v': /* command */
507 verbose++;
508 break;
509 case CHAR_MAX+2:
510 input_filename = optarg;
511 break;
512 }
513 }
515 c = optind;
516 if (wmax == -1 && argv[c])
517 wmax = atoi (argv[c++]);
518 if (cmax == -1 && argv[c])
519 cmax = atoi (argv[c++]);
520 if (statopts == NULL && argv[c]) {
521 asprintf (&statopts, "%s", argv[c++]);
522 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
523 options |= STAT;
524 }
526 return validate_arguments ();
527 }
531 int
532 validate_arguments ()
533 {
535 if (wmax >= 0 && wmin == -1)
536 wmin = 0;
537 if (cmax >= 0 && cmin == -1)
538 cmin = 0;
539 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
540 if (wmax > cmax && cmax != -1) {
541 printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
542 return ERROR;
543 }
544 if (cmin > wmin && wmin != -1) {
545 printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
546 return ERROR;
547 }
548 }
550 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
551 /* printf ("At least one threshold must be set\n"); */
552 /* return ERROR; */
553 /* } */
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;
574 }
578 /* Check thresholds against value */
579 int
580 check_thresholds (int value)
581 {
582 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
583 return OK;
584 }
585 else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
586 if (value > cmax && value < cmin)
587 return STATE_CRITICAL;
588 }
589 else if (cmax >= 0 && value > cmax) {
590 return STATE_CRITICAL;
591 }
592 else if (cmin >= 0 && value < cmin) {
593 return STATE_CRITICAL;
594 }
596 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
597 if (value > wmax && value < wmin) {
598 return STATE_WARNING;
599 }
600 }
601 else if (wmax >= 0 && value > wmax) {
602 return STATE_WARNING;
603 }
604 else if (wmin >= 0 && value < wmin) {
605 return STATE_WARNING;
606 }
607 return STATE_OK;
608 }
611 /* convert the elapsed time to seconds */
612 int
613 convert_to_seconds(char *etime) {
615 char *ptr;
616 int total;
618 int hyphcnt;
619 int coloncnt;
620 int days;
621 int hours;
622 int minutes;
623 int seconds;
625 hyphcnt = 0;
626 coloncnt = 0;
627 days = 0;
628 hours = 0;
629 minutes = 0;
630 seconds = 0;
632 for (ptr = etime; *ptr != '\0'; ptr++) {
634 if (*ptr == '-') {
635 hyphcnt++;
636 continue;
637 }
638 if (*ptr == ':') {
639 coloncnt++;
640 continue;
641 }
642 }
644 if (hyphcnt > 0) {
645 sscanf(etime, "%d-%d:%d:%d",
646 &days, &hours, &minutes, &seconds);
647 /* linux 2.6.5/2.6.6 reporting some processes with infinite
648 * elapsed times for some reason */
649 if (days == 49710) {
650 return 0;
651 }
652 } else {
653 if (coloncnt == 2) {
654 sscanf(etime, "%d:%d:%d",
655 &hours, &minutes, &seconds);
656 } else if (coloncnt == 1) {
657 sscanf(etime, "%d:%d",
658 &minutes, &seconds);
659 }
660 }
662 total = (days * 86400) +
663 (hours * 3600) +
664 (minutes * 60) +
665 seconds;
667 if (verbose >= 3 && metric == METRIC_ELAPSED) {
668 printf("seconds: %d\n", total);
669 }
670 return total;
671 }
674 void
675 print_help (void)
676 {
677 print_revision (progname, revision);
679 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
680 printf (COPYRIGHT, copyright, email);
682 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
683 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
684 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
686 printf ("\n\n");
688 print_usage ();
690 printf (_(UT_HELP_VRSN));
691 printf (_(UT_EXTRA_OPTS));
692 printf (" %s\n", "-w, --warning=RANGE");
693 printf (" %s\n", _("Generate warning state if metric is outside this range"));
694 printf (" %s\n", "-c, --critical=RANGE");
695 printf (" %s\n", _("Generate critical state if metric is outside this range"));
696 printf (" %s\n", "-m, --metric=TYPE");
697 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
698 printf (" %s\n", _("PROCS - number of processes (default)"));
699 printf (" %s\n", _("VSZ - virtual memory size"));
700 printf (" %s\n", _("RSS - resident set memory size"));
701 printf (" %s\n", _("CPU - percentage cpu"));
702 /* only linux etime is support currently */
703 #if defined( __linux__ )
704 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
705 #endif /* defined(__linux__) */
706 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
708 printf (" %s\n", "-v, --verbose");
709 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
711 printf ("\n");
712 printf ("%s\n", "Filters:");
713 printf (" %s\n", "-s, --state=STATUSFLAGS");
714 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
715 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
716 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
717 printf (" %s\n", "-p, --ppid=PPID");
718 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
719 printf (" %s\n", "-z, --vsz=VSZ");
720 printf (" %s\n", _("Only scan for processes with vsz higher than indicated."));
721 printf (" %s\n", "-r, --rss=RSS");
722 printf (" %s\n", _("Only scan for processes with rss higher than indicated."));
723 printf (" %s\n", "-P, --pcpu=PCPU");
724 printf (" %s\n", _("Only scan for processes with pcpu higher than indicated."));
725 printf (" %s\n", "-u, --user=USER");
726 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
727 printf (" %s\n", "-a, --argument-array=STRING");
728 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
729 printf (" %s\n", "--ereg-argument-array=STRING");
730 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
731 printf (" %s\n", "-C, --command=COMMAND");
732 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
734 printf(_("\n\
735 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
736 specified 'max:min', a warning status will be generated if the\n\
737 count is inside the specified range\n\n"));
739 printf(_("\
740 This plugin checks the number of currently running processes and\n\
741 generates WARNING or CRITICAL states if the process count is outside\n\
742 the specified threshold ranges. The process count can be filtered by\n\
743 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
744 be the total number of running processes\n\n"));
746 #ifdef NP_EXTRA_OPTS
747 printf ("%s\n", _("Notes:"));
748 printf (_(UT_EXTRA_OPTS_NOTES));
749 printf ("\n");
750 #endif
752 printf ("%s\n", _("Examples:"));
753 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
754 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
755 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
756 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
757 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
758 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
759 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
760 printf (" %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
761 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
762 printf (" %s\n", _("Alert if cpu of any processes over 10%% or 20%%"));
764 printf (_(UT_SUPPORT));
765 }
767 void
768 print_usage (void)
769 {
770 printf (_("Usage: "));
771 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
772 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
773 printf (" [-C command] [-t timeout] [-v]\n");
774 }