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"
47 #include <pwd.h>
49 int process_arguments (int, char **);
50 int validate_arguments (void);
51 int check_thresholds (int);
52 int convert_to_seconds (char *);
53 void print_help (void);
54 void print_usage (void);
56 int wmax = -1;
57 int cmax = -1;
58 int wmin = -1;
59 int cmin = -1;
61 int options = 0; /* bitmask of filter criteria to test against */
62 #define ALL 1
63 #define STAT 2
64 #define PPID 4
65 #define USER 8
66 #define PROG 16
67 #define ARGS 32
68 #define VSZ 64
69 #define RSS 128
70 #define PCPU 256
71 #define ELAPSED 512
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
80 };
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 *fmt;
93 char *fails;
94 char tmp[MAX_INPUT_BUFFER];
98 int
99 main (int argc, char **argv)
100 {
101 char *input_buffer;
102 char *input_line;
103 char *procprog;
105 pid_t mypid = 0;
106 int procuid = 0;
107 pid_t procpid = 0;
108 pid_t procppid = 0;
109 int procvsz = 0;
110 int procrss = 0;
111 int procseconds = 0;
112 float procpcpu = 0;
113 char procstat[8];
114 char procetime[MAX_INPUT_BUFFER] = { '\0' };
115 char *procargs;
117 const char *zombie = "Z";
119 int resultsum = 0; /* bitmask of the filter criteria met by a process */
120 int found = 0; /* counter for number of lines returned in `ps` output */
121 int procs = 0; /* counter for number of processes meeting filter criteria */
122 int pos; /* number of spaces before 'args' in `ps` output */
123 int cols; /* number of columns in ps output */
124 int expected_cols = PS_COLS - 1;
125 int warn = 0; /* number of processes in warn state */
126 int crit = 0; /* number of processes in crit state */
127 int i = 0;
128 int result = STATE_UNKNOWN;
130 setlocale (LC_ALL, "");
131 bindtextdomain (PACKAGE, LOCALEDIR);
132 textdomain (PACKAGE);
133 setlocale(LC_NUMERIC, "POSIX");
135 input_buffer = malloc (MAX_INPUT_BUFFER);
136 procprog = malloc (MAX_INPUT_BUFFER);
138 asprintf (&metric_name, "PROCS");
139 metric = METRIC_PROCS;
141 if (process_arguments (argc, argv) == ERROR)
142 usage4 (_("Could not parse arguments"));
144 /* get our pid */
145 mypid = getpid();
147 /* Set signal handling and alarm timeout */
148 if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
149 usage4 (_("Cannot catch SIGALRM"));
150 }
151 alarm (timeout_interval);
153 if (verbose >= 2)
154 printf (_("CMD: %s\n"), PS_COMMAND);
156 child_process = spopen (PS_COMMAND);
157 if (child_process == NULL) {
158 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
159 return STATE_UNKNOWN;
160 }
162 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
163 if (child_stderr == NULL)
164 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
166 /* flush first line */
167 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
168 while ( input_buffer[strlen(input_buffer)-1] != '\n' )
169 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
171 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
172 asprintf (&input_line, "%s", input_buffer);
173 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
174 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
175 asprintf (&input_line, "%s%s", input_line, input_buffer);
176 }
178 if (verbose >= 3)
179 printf ("%s", input_line);
181 strcpy (procprog, "");
182 asprintf (&procargs, "%s", "");
184 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
186 /* Zombie processes do not give a procprog command */
187 if ( cols < expected_cols && strstr(procstat, zombie) ) {
188 cols = expected_cols;
189 }
190 if ( cols >= expected_cols ) {
191 resultsum = 0;
192 asprintf (&procargs, "%s", input_line + pos);
193 strip (procargs);
195 /* Some ps return full pathname for command. This removes path */
196 strcpy(procprog, base_name(procprog));
198 /* we need to convert the elapsed time to seconds */
199 procseconds = convert_to_seconds(procetime);
201 if (verbose >= 3)
202 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
203 procs, procuid, procvsz, procrss,
204 procpid, procppid, procpcpu, procstat,
205 procetime, procprog, procargs);
207 /* Ignore self */
208 if (mypid == procpid) continue;
210 if ((options & STAT) && (strstr (statopts, procstat)))
211 resultsum |= STAT;
212 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
213 resultsum |= ARGS;
214 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
215 resultsum |= PROG;
216 if ((options & PPID) && (procppid == ppid))
217 resultsum |= PPID;
218 if ((options & USER) && (procuid == uid))
219 resultsum |= USER;
220 if ((options & VSZ) && (procvsz >= vsz))
221 resultsum |= VSZ;
222 if ((options & RSS) && (procrss >= rss))
223 resultsum |= RSS;
224 if ((options & PCPU) && (procpcpu >= pcpu))
225 resultsum |= PCPU;
227 found++;
229 /* Next line if filters not matched */
230 if (!(options == resultsum || options == ALL))
231 continue;
233 procs++;
235 if (metric == METRIC_VSZ)
236 i = check_thresholds (procvsz);
237 else if (metric == METRIC_RSS)
238 i = check_thresholds (procrss);
239 /* TODO? float thresholds for --metric=CPU */
240 else if (metric == METRIC_CPU)
241 i = check_thresholds ((int)procpcpu);
242 else if (metric == METRIC_ELAPSED)
243 i = check_thresholds (procseconds);
245 if (metric != METRIC_PROCS) {
246 if (i == STATE_WARNING) {
247 warn++;
248 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
249 result = max_state (result, i);
250 }
251 if (i == STATE_CRITICAL) {
252 crit++;
253 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
254 result = max_state (result, i);
255 }
256 }
257 }
258 /* This should not happen */
259 else if (verbose) {
260 printf(_("Not parseable: %s"), input_buffer);
261 }
262 }
264 /* If we get anything on STDERR, at least set warning */
265 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
266 if (verbose)
267 printf ("STDERR: %s", input_buffer);
268 result = max_state (result, STATE_WARNING);
269 printf (_("System call sent warnings to stderr\n"));
270 }
272 (void) fclose (child_stderr);
274 /* close the pipe */
275 if (spclose (child_process)) {
276 printf (_("System call returned nonzero status\n"));
277 result = max_state (result, STATE_WARNING);
278 }
280 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
281 printf (_("Unable to read output\n"));
282 return result;
283 }
285 if ( result == STATE_UNKNOWN )
286 result = STATE_OK;
288 /* Needed if procs found, but none match filter */
289 if ( metric == METRIC_PROCS ) {
290 result = max_state (result, check_thresholds (procs) );
291 }
293 if ( result == STATE_OK ) {
294 printf ("%s %s: ", metric_name, _("OK"));
295 } else if (result == STATE_WARNING) {
296 printf ("%s %s: ", metric_name, _("WARNING"));
297 if ( metric != METRIC_PROCS ) {
298 printf (_("%d warn out of "), warn);
299 }
300 } else if (result == STATE_CRITICAL) {
301 printf ("%s %s: ", metric_name, _("CRITICAL"));
302 if (metric != METRIC_PROCS) {
303 printf (_("%d crit, %d warn out of "), crit, warn);
304 }
305 }
306 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
308 if (strcmp(fmt,"") != 0) {
309 printf (_(" with %s"), fmt);
310 }
312 if ( verbose >= 1 && strcmp(fails,"") )
313 printf (" [%s]", fails);
315 printf ("\n");
316 return result;
317 }
321 /* process command-line arguments */
322 int
323 process_arguments (int argc, char **argv)
324 {
325 int c = 1;
326 char *user;
327 struct passwd *pw;
328 int option = 0;
329 static struct option longopts[] = {
330 {"warning", required_argument, 0, 'w'},
331 {"critical", required_argument, 0, 'c'},
332 {"metric", required_argument, 0, 'm'},
333 {"timeout", required_argument, 0, 't'},
334 {"status", required_argument, 0, 's'},
335 {"ppid", required_argument, 0, 'p'},
336 {"command", required_argument, 0, 'C'},
337 {"vsz", required_argument, 0, 'z'},
338 {"rss", required_argument, 0, 'r'},
339 {"pcpu", required_argument, 0, 'P'},
340 {"elapsed", required_argument, 0, 'e'},
341 {"argument-array", required_argument, 0, 'a'},
342 {"help", no_argument, 0, 'h'},
343 {"version", no_argument, 0, 'V'},
344 {"verbose", no_argument, 0, 'v'},
345 {0, 0, 0, 0}
346 };
348 for (c = 1; c < argc; c++)
349 if (strcmp ("-to", argv[c]) == 0)
350 strcpy (argv[c], "-t");
352 while (1) {
353 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
354 longopts, &option);
356 if (c == -1 || c == EOF)
357 break;
359 switch (c) {
360 case '?': /* help */
361 usage5 ();
362 case 'h': /* help */
363 print_help ();
364 exit (STATE_OK);
365 case 'V': /* version */
366 print_revision (progname, revision);
367 exit (STATE_OK);
368 case 't': /* timeout period */
369 if (!is_integer (optarg))
370 usage2 (_("Timeout interval must be a positive integer"), optarg);
371 else
372 timeout_interval = atoi (optarg);
373 break;
374 case 'c': /* critical threshold */
375 if (is_integer (optarg))
376 cmax = atoi (optarg);
377 else if (sscanf (optarg, ":%d", &cmax) == 1)
378 break;
379 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
380 break;
381 else if (sscanf (optarg, "%d:", &cmin) == 1)
382 break;
383 else
384 usage4 (_("Critical Process Count must be an integer!"));
385 break;
386 case 'w': /* warning threshold */
387 if (is_integer (optarg))
388 wmax = atoi (optarg);
389 else if (sscanf (optarg, ":%d", &wmax) == 1)
390 break;
391 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
392 break;
393 else if (sscanf (optarg, "%d:", &wmin) == 1)
394 break;
395 else
396 usage4 (_("Warning Process Count must be an integer!"));
397 break;
398 case 'p': /* process id */
399 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
400 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
401 options |= PPID;
402 break;
403 }
404 usage4 (_("Parent Process ID must be an integer!"));
405 case 's': /* status */
406 if (statopts)
407 break;
408 else
409 statopts = optarg;
410 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
411 options |= STAT;
412 break;
413 case 'u': /* user or user id */
414 if (is_integer (optarg)) {
415 uid = atoi (optarg);
416 pw = getpwuid ((uid_t) uid);
417 /* check to be sure user exists */
418 if (pw == NULL)
419 usage2 (_("UID was not found"), optarg);
420 }
421 else {
422 pw = getpwnam (optarg);
423 /* check to be sure user exists */
424 if (pw == NULL)
425 usage2 (_("User name was not found"), optarg);
426 /* then get uid */
427 uid = pw->pw_uid;
428 }
429 user = pw->pw_name;
430 asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
431 uid, user);
432 options |= USER;
433 break;
434 case 'C': /* command */
435 /* TODO: allow this to be passed in with --metric */
436 if (prog)
437 break;
438 else
439 prog = optarg;
440 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
441 prog);
442 options |= PROG;
443 break;
444 case 'a': /* args (full path name with args) */
445 /* TODO: allow this to be passed in with --metric */
446 if (args)
447 break;
448 else
449 args = optarg;
450 asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
451 options |= ARGS;
452 break;
453 case 'r': /* RSS */
454 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
455 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
456 options |= RSS;
457 break;
458 }
459 usage4 (_("RSS must be an integer!"));
460 case 'z': /* VSZ */
461 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
462 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
463 options |= VSZ;
464 break;
465 }
466 usage4 (_("VSZ must be an integer!"));
467 case 'P': /* PCPU */
468 /* TODO: -P 1.5.5 is accepted */
469 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
470 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
471 options |= PCPU;
472 break;
473 }
474 usage4 (_("PCPU must be a float!"));
475 case 'm':
476 asprintf (&metric_name, "%s", optarg);
477 if ( strcmp(optarg, "PROCS") == 0) {
478 metric = METRIC_PROCS;
479 break;
480 }
481 else if ( strcmp(optarg, "VSZ") == 0) {
482 metric = METRIC_VSZ;
483 break;
484 }
485 else if ( strcmp(optarg, "RSS") == 0 ) {
486 metric = METRIC_RSS;
487 break;
488 }
489 else if ( strcmp(optarg, "CPU") == 0 ) {
490 metric = METRIC_CPU;
491 break;
492 }
493 else if ( strcmp(optarg, "ELAPSED") == 0) {
494 metric = METRIC_ELAPSED;
495 break;
496 }
498 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
499 case 'v': /* command */
500 verbose++;
501 break;
502 }
503 }
505 c = optind;
506 if (wmax == -1 && argv[c])
507 wmax = atoi (argv[c++]);
508 if (cmax == -1 && argv[c])
509 cmax = atoi (argv[c++]);
510 if (statopts == NULL && argv[c]) {
511 asprintf (&statopts, "%s", argv[c++]);
512 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
513 options |= STAT;
514 }
516 return validate_arguments ();
517 }
521 int
522 validate_arguments ()
523 {
525 if (wmax >= 0 && wmin == -1)
526 wmin = 0;
527 if (cmax >= 0 && cmin == -1)
528 cmin = 0;
529 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
530 if (wmax > cmax && cmax != -1) {
531 printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
532 return ERROR;
533 }
534 if (cmin > wmin && wmin != -1) {
535 printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
536 return ERROR;
537 }
538 }
540 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
541 /* printf ("At least one threshold must be set\n"); */
542 /* return ERROR; */
543 /* } */
545 if (options == 0)
546 options = ALL;
548 if (statopts==NULL)
549 statopts = strdup("");
551 if (prog==NULL)
552 prog = strdup("");
554 if (args==NULL)
555 args = strdup("");
557 if (fmt==NULL)
558 fmt = strdup("");
560 if (fails==NULL)
561 fails = strdup("");
563 return options;
564 }
568 /* Check thresholds against value */
569 int
570 check_thresholds (int value)
571 {
572 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
573 return OK;
574 }
575 else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
576 if (value > cmax && value < cmin)
577 return STATE_CRITICAL;
578 }
579 else if (cmax >= 0 && value > cmax) {
580 return STATE_CRITICAL;
581 }
582 else if (cmin >= 0 && value < cmin) {
583 return STATE_CRITICAL;
584 }
586 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
587 if (value > wmax && value < wmin) {
588 return STATE_WARNING;
589 }
590 }
591 else if (wmax >= 0 && value > wmax) {
592 return STATE_WARNING;
593 }
594 else if (wmin >= 0 && value < wmin) {
595 return STATE_WARNING;
596 }
597 return STATE_OK;
598 }
601 /* convert the elapsed time to seconds */
602 int
603 convert_to_seconds(char *etime) {
605 char *ptr;
606 int total;
608 int hyphcnt;
609 int coloncnt;
610 int days;
611 int hours;
612 int minutes;
613 int seconds;
615 hyphcnt = 0;
616 coloncnt = 0;
617 days = 0;
618 hours = 0;
619 minutes = 0;
620 seconds = 0;
622 for (ptr = etime; *ptr != '\0'; ptr++) {
624 if (*ptr == '-') {
625 hyphcnt++;
626 continue;
627 }
628 if (*ptr == ':') {
629 coloncnt++;
630 continue;
631 }
632 }
634 if (hyphcnt > 0) {
635 sscanf(etime, "%d-%d:%d:%d",
636 &days, &hours, &minutes, &seconds);
637 /* linux 2.6.5/2.6.6 reporting some processes with infinite
638 * elapsed times for some reason */
639 if (days == 49710) {
640 return 0;
641 }
642 } else {
643 if (coloncnt == 2) {
644 sscanf(etime, "%d:%d:%d",
645 &hours, &minutes, &seconds);
646 } else if (coloncnt == 1) {
647 sscanf(etime, "%d:%d",
648 &minutes, &seconds);
649 }
650 }
652 total = (days * 86400) +
653 (hours * 3600) +
654 (minutes * 60) +
655 seconds;
657 if (verbose >= 3 && metric == METRIC_ELAPSED) {
658 printf("seconds: %d\n", total);
659 }
660 return total;
661 }
664 void
665 print_help (void)
666 {
667 print_revision (progname, revision);
669 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
670 printf (COPYRIGHT, copyright, email);
672 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
673 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
674 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
676 printf ("\n\n");
678 print_usage ();
680 printf ("%s\n", _("Required Arguments:"));
681 printf (" %s\n", "-w, --warning=RANGE");
682 printf (" %s\n", _("Generate warning state if metric is outside this range"));
683 printf (" %s\n", "-c, --critical=RANGE");
684 printf (" %s\n", _("Generate critical state if metric is outside this range"));
686 printf ("%s\n", _("Optional Arguments:"));
687 printf (" %s\n", "-m, --metric=TYPE");
688 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
689 printf (" %s\n", _("PROCS - number of processes (default)"));
690 printf (" %s\n", _("VSZ - virtual memory size"));
691 printf (" %s\n", _("RSS - resident set memory size"));
692 printf (" %s\n", _("CPU - percentage cpu"));
693 /* only linux etime is support currently */
694 #if defined( __linux__ )
695 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
696 #endif /* defined(__linux__) */
697 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
699 printf (" %s\n", "-v, --verbose");
700 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
702 printf ("%s\n", "Optional Filters:");
703 printf (" %s\n", "-s, --state=STATUSFLAGS");
704 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
705 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
706 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
707 printf (" %s\n", "-p, --ppid=PPID");
708 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
709 printf (" %s\n", "-z, --vsz=VSZ");
710 printf (" %s\n", _("Only scan for processes with vsz higher than indicated."));
711 printf (" %s\n", "-r, --rss=RSS");
712 printf (" %s\n", _("Only scan for processes with rss higher than indicated."));
713 printf (" %s\n", "-P, --pcpu=PCPU");
714 printf (" %s\n", _("Only scan for processes with pcpu higher than indicated."));
715 printf (" %s\n", "-u, --user=USER");
716 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
717 printf (" %s\n", "-a, --argument-array=STRING");
718 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
719 printf (" %s\n", "-C, --command=COMMAND");
720 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
722 printf(_("\n\
723 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
724 specified 'max:min', a warning status will be generated if the\n\
725 count is inside the specified range\n\n"));
727 printf(_("\
728 This plugin checks the number of currently running processes and\n\
729 generates WARNING or CRITICAL states if the process count is outside\n\
730 the specified threshold ranges. The process count can be filtered by\n\
731 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
732 be the total number of running processes\n\n"));
734 printf ("%s\n", _("Examples:"));
735 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
736 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
737 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
738 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
739 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
740 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
741 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
742 printf (" %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
743 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
744 printf (" %s\n\n", _("Alert if cpu of any processes over 10%% or 20%%"));
746 printf (_(UT_SUPPORT));
747 }
749 void
750 print_usage (void)
751 {
752 printf (_("Usage: "));
753 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
754 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
755 printf (" [-C command] [-t timeout] [-v]\n");
756 }