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 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;
133 int result = STATE_UNKNOWN;
135 setlocale (LC_ALL, "");
136 bindtextdomain (PACKAGE, LOCALEDIR);
137 textdomain (PACKAGE);
138 setlocale(LC_NUMERIC, "POSIX");
140 input_buffer = malloc (MAX_INPUT_BUFFER);
141 procprog = malloc (MAX_INPUT_BUFFER);
143 asprintf (&metric_name, "PROCS");
144 metric = METRIC_PROCS;
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, popen_timeout_alarm_handler) == SIG_ERR) {
154 usage4 (_("Cannot catch SIGALRM"));
155 }
156 alarm (timeout_interval);
158 if (verbose >= 2)
159 printf (_("CMD: %s\n"), PS_COMMAND);
161 if (input_filename == NULL) {
162 ps_input = spopen (PS_COMMAND);
163 if (ps_input == NULL) {
164 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
165 return STATE_UNKNOWN;
166 }
167 child_stderr = fdopen (child_stderr_array[fileno (ps_input)], "r");
168 if (child_stderr == NULL)
169 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
170 } else {
171 ps_input = fopen(input_filename, "r");
172 if (ps_input == NULL) {
173 die( STATE_UNKNOWN, _("Error opening %s\n"), input_filename );
174 }
175 }
177 /* flush first line */
178 fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
179 while ( input_buffer[strlen(input_buffer)-1] != '\n' )
180 fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
182 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input)) {
183 asprintf (&input_line, "%s", input_buffer);
184 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
185 fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
186 asprintf (&input_line, "%s%s", input_line, input_buffer);
187 }
189 if (verbose >= 3)
190 printf ("%s", input_line);
192 strcpy (procprog, "");
193 asprintf (&procargs, "%s", "");
195 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
197 /* Zombie processes do not give a procprog command */
198 if ( cols < expected_cols && strstr(procstat, zombie) ) {
199 cols = expected_cols;
200 }
201 if ( cols >= expected_cols ) {
202 resultsum = 0;
203 asprintf (&procargs, "%s", input_line + pos);
204 strip (procargs);
206 /* Some ps return full pathname for command. This removes path */
207 strcpy(procprog, base_name(procprog));
209 /* we need to convert the elapsed time to seconds */
210 procseconds = convert_to_seconds(procetime);
212 if (verbose >= 3)
213 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
214 procs, procuid, procvsz, procrss,
215 procpid, procppid, procpcpu, procstat,
216 procetime, procprog, procargs);
218 /* Ignore self */
219 if (mypid == procpid) continue;
221 if ((options & STAT) && (strstr (statopts, procstat)))
222 resultsum |= STAT;
223 if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
224 resultsum |= ARGS;
225 if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
226 resultsum |= EREG_ARGS;
227 if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
228 resultsum |= PROG;
229 if ((options & PPID) && (procppid == ppid))
230 resultsum |= PPID;
231 if ((options & USER) && (procuid == uid))
232 resultsum |= USER;
233 if ((options & VSZ) && (procvsz >= vsz))
234 resultsum |= VSZ;
235 if ((options & RSS) && (procrss >= rss))
236 resultsum |= RSS;
237 if ((options & PCPU) && (procpcpu >= pcpu))
238 resultsum |= PCPU;
240 found++;
242 /* Next line if filters not matched */
243 if (!(options == resultsum || options == ALL))
244 continue;
246 procs++;
247 if (verbose >= 2) {
248 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
249 procuid, procvsz, procrss,
250 procpid, procppid, procpcpu, procstat,
251 procetime, procprog, procargs);
252 }
254 if (metric == METRIC_VSZ)
255 i = check_thresholds (procvsz);
256 else if (metric == METRIC_RSS)
257 i = check_thresholds (procrss);
258 /* TODO? float thresholds for --metric=CPU */
259 else if (metric == METRIC_CPU)
260 i = check_thresholds ((int)procpcpu);
261 else if (metric == METRIC_ELAPSED)
262 i = check_thresholds (procseconds);
264 if (metric != METRIC_PROCS) {
265 if (i == STATE_WARNING) {
266 warn++;
267 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
268 result = max_state (result, i);
269 }
270 if (i == STATE_CRITICAL) {
271 crit++;
272 asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
273 result = max_state (result, i);
274 }
275 }
276 }
277 /* This should not happen */
278 else if (verbose) {
279 printf(_("Not parseable: %s"), input_buffer);
280 }
281 }
283 /* If we get anything on STDERR, at least set warning */
284 if (input_filename == NULL) {
285 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
286 if (verbose)
287 printf ("STDERR: %s", input_buffer);
288 result = max_state (result, STATE_WARNING);
289 printf (_("System call sent warnings to stderr\n"));
290 }
292 (void) fclose (child_stderr);
294 /* close the pipe */
295 if (spclose (ps_input)) {
296 printf (_("System call returned nonzero status\n"));
297 result = max_state (result, STATE_WARNING);
298 }
299 }
301 if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
302 printf (_("Unable to read output\n"));
303 return result;
304 }
306 if ( result == STATE_UNKNOWN )
307 result = STATE_OK;
309 /* Needed if procs found, but none match filter */
310 if ( metric == METRIC_PROCS ) {
311 result = max_state (result, check_thresholds (procs) );
312 }
314 if ( result == STATE_OK ) {
315 printf ("%s %s: ", metric_name, _("OK"));
316 } else if (result == STATE_WARNING) {
317 printf ("%s %s: ", metric_name, _("WARNING"));
318 if ( metric != METRIC_PROCS ) {
319 printf (_("%d warn out of "), warn);
320 }
321 } else if (result == STATE_CRITICAL) {
322 printf ("%s %s: ", metric_name, _("CRITICAL"));
323 if (metric != METRIC_PROCS) {
324 printf (_("%d crit, %d warn out of "), crit, warn);
325 }
326 }
327 printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
329 if (strcmp(fmt,"") != 0) {
330 printf (_(" with %s"), fmt);
331 }
333 if ( verbose >= 1 && strcmp(fails,"") )
334 printf (" [%s]", fails);
336 printf ("\n");
337 return result;
338 }
342 /* process command-line arguments */
343 int
344 process_arguments (int argc, char **argv)
345 {
346 int c = 1;
347 char *user;
348 struct passwd *pw;
349 int option = 0;
350 int err;
351 int cflags = REG_NOSUB | REG_EXTENDED;
352 char errbuf[MAX_INPUT_BUFFER];
353 static struct option longopts[] = {
354 {"warning", required_argument, 0, 'w'},
355 {"critical", required_argument, 0, 'c'},
356 {"metric", required_argument, 0, 'm'},
357 {"timeout", required_argument, 0, 't'},
358 {"status", required_argument, 0, 's'},
359 {"ppid", required_argument, 0, 'p'},
360 {"command", required_argument, 0, 'C'},
361 {"vsz", required_argument, 0, 'z'},
362 {"rss", required_argument, 0, 'r'},
363 {"pcpu", required_argument, 0, 'P'},
364 {"elapsed", required_argument, 0, 'e'},
365 {"argument-array", required_argument, 0, 'a'},
366 {"help", no_argument, 0, 'h'},
367 {"version", no_argument, 0, 'V'},
368 {"verbose", no_argument, 0, 'v'},
369 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
370 {"input-file", required_argument, 0, CHAR_MAX+2},
371 {0, 0, 0, 0}
372 };
374 for (c = 1; c < argc; c++)
375 if (strcmp ("-to", argv[c]) == 0)
376 strcpy (argv[c], "-t");
378 while (1) {
379 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
380 longopts, &option);
382 if (c == -1 || c == EOF)
383 break;
385 switch (c) {
386 case '?': /* help */
387 usage5 ();
388 case 'h': /* help */
389 print_help ();
390 exit (STATE_OK);
391 case 'V': /* version */
392 print_revision (progname, revision);
393 exit (STATE_OK);
394 case 't': /* timeout period */
395 if (!is_integer (optarg))
396 usage2 (_("Timeout interval must be a positive integer"), optarg);
397 else
398 timeout_interval = atoi (optarg);
399 break;
400 case 'c': /* critical threshold */
401 if (is_integer (optarg))
402 cmax = atoi (optarg);
403 else if (sscanf (optarg, ":%d", &cmax) == 1)
404 break;
405 else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
406 break;
407 else if (sscanf (optarg, "%d:", &cmin) == 1)
408 break;
409 else
410 usage4 (_("Critical Process Count must be an integer!"));
411 break;
412 case 'w': /* warning threshold */
413 if (is_integer (optarg))
414 wmax = atoi (optarg);
415 else if (sscanf (optarg, ":%d", &wmax) == 1)
416 break;
417 else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
418 break;
419 else if (sscanf (optarg, "%d:", &wmin) == 1)
420 break;
421 else
422 usage4 (_("Warning Process Count must be an integer!"));
423 break;
424 case 'p': /* process id */
425 if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
426 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
427 options |= PPID;
428 break;
429 }
430 usage4 (_("Parent Process ID must be an integer!"));
431 case 's': /* status */
432 if (statopts)
433 break;
434 else
435 statopts = optarg;
436 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
437 options |= STAT;
438 break;
439 case 'u': /* user or user id */
440 if (is_integer (optarg)) {
441 uid = atoi (optarg);
442 pw = getpwuid ((uid_t) uid);
443 /* check to be sure user exists */
444 if (pw == NULL)
445 usage2 (_("UID was not found"), optarg);
446 }
447 else {
448 pw = getpwnam (optarg);
449 /* check to be sure user exists */
450 if (pw == NULL)
451 usage2 (_("User name was not found"), optarg);
452 /* then get uid */
453 uid = pw->pw_uid;
454 }
455 user = pw->pw_name;
456 asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
457 uid, user);
458 options |= USER;
459 break;
460 case 'C': /* command */
461 /* TODO: allow this to be passed in with --metric */
462 if (prog)
463 break;
464 else
465 prog = optarg;
466 asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
467 prog);
468 options |= PROG;
469 break;
470 case 'a': /* args (full path name with args) */
471 /* TODO: allow this to be passed in with --metric */
472 if (args)
473 break;
474 else
475 args = optarg;
476 asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
477 options |= ARGS;
478 break;
479 case CHAR_MAX+1:
480 err = regcomp(&re_args, optarg, cflags);
481 if (err != 0) {
482 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
483 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
484 }
485 asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
486 options |= EREG_ARGS;
487 break;
488 case 'r': /* RSS */
489 if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
490 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
491 options |= RSS;
492 break;
493 }
494 usage4 (_("RSS must be an integer!"));
495 case 'z': /* VSZ */
496 if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
497 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
498 options |= VSZ;
499 break;
500 }
501 usage4 (_("VSZ must be an integer!"));
502 case 'P': /* PCPU */
503 /* TODO: -P 1.5.5 is accepted */
504 if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
505 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
506 options |= PCPU;
507 break;
508 }
509 usage4 (_("PCPU must be a float!"));
510 case 'm':
511 asprintf (&metric_name, "%s", optarg);
512 if ( strcmp(optarg, "PROCS") == 0) {
513 metric = METRIC_PROCS;
514 break;
515 }
516 else if ( strcmp(optarg, "VSZ") == 0) {
517 metric = METRIC_VSZ;
518 break;
519 }
520 else if ( strcmp(optarg, "RSS") == 0 ) {
521 metric = METRIC_RSS;
522 break;
523 }
524 else if ( strcmp(optarg, "CPU") == 0 ) {
525 metric = METRIC_CPU;
526 break;
527 }
528 else if ( strcmp(optarg, "ELAPSED") == 0) {
529 metric = METRIC_ELAPSED;
530 break;
531 }
533 usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
534 case 'v': /* command */
535 verbose++;
536 break;
537 case CHAR_MAX+2:
538 input_filename = optarg;
539 break;
540 }
541 }
543 c = optind;
544 if (wmax == -1 && argv[c])
545 wmax = atoi (argv[c++]);
546 if (cmax == -1 && argv[c])
547 cmax = atoi (argv[c++]);
548 if (statopts == NULL && argv[c]) {
549 asprintf (&statopts, "%s", argv[c++]);
550 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
551 options |= STAT;
552 }
554 return validate_arguments ();
555 }
559 int
560 validate_arguments ()
561 {
563 if (wmax >= 0 && wmin == -1)
564 wmin = 0;
565 if (cmax >= 0 && cmin == -1)
566 cmin = 0;
567 if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
568 if (wmax > cmax && cmax != -1) {
569 printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
570 return ERROR;
571 }
572 if (cmin > wmin && wmin != -1) {
573 printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
574 return ERROR;
575 }
576 }
578 /* if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
579 /* printf ("At least one threshold must be set\n"); */
580 /* return ERROR; */
581 /* } */
583 if (options == 0)
584 options = ALL;
586 if (statopts==NULL)
587 statopts = strdup("");
589 if (prog==NULL)
590 prog = strdup("");
592 if (args==NULL)
593 args = strdup("");
595 if (fmt==NULL)
596 fmt = strdup("");
598 if (fails==NULL)
599 fails = strdup("");
601 return options;
602 }
606 /* Check thresholds against value */
607 int
608 check_thresholds (int value)
609 {
610 if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
611 return OK;
612 }
613 else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
614 if (value > cmax && value < cmin)
615 return STATE_CRITICAL;
616 }
617 else if (cmax >= 0 && value > cmax) {
618 return STATE_CRITICAL;
619 }
620 else if (cmin >= 0 && value < cmin) {
621 return STATE_CRITICAL;
622 }
624 if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
625 if (value > wmax && value < wmin) {
626 return STATE_WARNING;
627 }
628 }
629 else if (wmax >= 0 && value > wmax) {
630 return STATE_WARNING;
631 }
632 else if (wmin >= 0 && value < wmin) {
633 return STATE_WARNING;
634 }
635 return STATE_OK;
636 }
639 /* convert the elapsed time to seconds */
640 int
641 convert_to_seconds(char *etime) {
643 char *ptr;
644 int total;
646 int hyphcnt;
647 int coloncnt;
648 int days;
649 int hours;
650 int minutes;
651 int seconds;
653 hyphcnt = 0;
654 coloncnt = 0;
655 days = 0;
656 hours = 0;
657 minutes = 0;
658 seconds = 0;
660 for (ptr = etime; *ptr != '\0'; ptr++) {
662 if (*ptr == '-') {
663 hyphcnt++;
664 continue;
665 }
666 if (*ptr == ':') {
667 coloncnt++;
668 continue;
669 }
670 }
672 if (hyphcnt > 0) {
673 sscanf(etime, "%d-%d:%d:%d",
674 &days, &hours, &minutes, &seconds);
675 /* linux 2.6.5/2.6.6 reporting some processes with infinite
676 * elapsed times for some reason */
677 if (days == 49710) {
678 return 0;
679 }
680 } else {
681 if (coloncnt == 2) {
682 sscanf(etime, "%d:%d:%d",
683 &hours, &minutes, &seconds);
684 } else if (coloncnt == 1) {
685 sscanf(etime, "%d:%d",
686 &minutes, &seconds);
687 }
688 }
690 total = (days * 86400) +
691 (hours * 3600) +
692 (minutes * 60) +
693 seconds;
695 if (verbose >= 3 && metric == METRIC_ELAPSED) {
696 printf("seconds: %d\n", total);
697 }
698 return total;
699 }
702 void
703 print_help (void)
704 {
705 print_revision (progname, revision);
707 printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
708 printf (COPYRIGHT, copyright, email);
710 printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
711 printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
712 printf ("%s\n", _("of processes. Search filters can be applied to limit the processes to check."));
714 printf ("\n\n");
716 print_usage ();
718 printf ("%s\n", _("Required Arguments:"));
719 printf (" %s\n", "-w, --warning=RANGE");
720 printf (" %s\n", _("Generate warning state if metric is outside this range"));
721 printf (" %s\n", "-c, --critical=RANGE");
722 printf (" %s\n", _("Generate critical state if metric is outside this range"));
724 printf ("%s\n", _("Optional Arguments:"));
725 printf (" %s\n", "-m, --metric=TYPE");
726 printf (" %s\n", _("Check thresholds against metric. Valid types:"));
727 printf (" %s\n", _("PROCS - number of processes (default)"));
728 printf (" %s\n", _("VSZ - virtual memory size"));
729 printf (" %s\n", _("RSS - resident set memory size"));
730 printf (" %s\n", _("CPU - percentage cpu"));
731 /* only linux etime is support currently */
732 #if defined( __linux__ )
733 printf (" %s\n", _("ELAPSED - time elapsed in seconds"));
734 #endif /* defined(__linux__) */
735 printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
737 printf (" %s\n", "-v, --verbose");
738 printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
740 printf ("%s\n", "Optional Filters:");
741 printf (" %s\n", "-s, --state=STATUSFLAGS");
742 printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
743 printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
744 printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
745 printf (" %s\n", "-p, --ppid=PPID");
746 printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
747 printf (" %s\n", "-z, --vsz=VSZ");
748 printf (" %s\n", _("Only scan for processes with vsz higher than indicated."));
749 printf (" %s\n", "-r, --rss=RSS");
750 printf (" %s\n", _("Only scan for processes with rss higher than indicated."));
751 printf (" %s\n", "-P, --pcpu=PCPU");
752 printf (" %s\n", _("Only scan for processes with pcpu higher than indicated."));
753 printf (" %s\n", "-u, --user=USER");
754 printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
755 printf (" %s\n", "-a, --argument-array=STRING");
756 printf (" %s\n", _("Only scan for processes with args that contain STRING."));
757 printf (" %s\n", "--ereg-argument-array=STRING");
758 printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
759 printf (" %s\n", "-C, --command=COMMAND");
760 printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
762 printf(_("\n\
763 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
764 specified 'max:min', a warning status will be generated if the\n\
765 count is inside the specified range\n\n"));
767 printf(_("\
768 This plugin checks the number of currently running processes and\n\
769 generates WARNING or CRITICAL states if the process count is outside\n\
770 the specified threshold ranges. The process count can be filtered by\n\
771 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
772 be the total number of running processes\n\n"));
774 printf ("%s\n", _("Examples:"));
775 printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
776 printf (" %s\n", _("Warning if not two processes with command name portsentry."));
777 printf (" %s\n\n", _("Critical if < 2 or > 1024 processes"));
778 printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
779 printf (" %s\n", _("Warning alert if > 10 processes with command arguments containing"));
780 printf (" %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
781 printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
782 printf (" %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
783 printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
784 printf (" %s\n", _("Alert if cpu of any processes over 10%% or 20%%"));
786 printf (_(UT_SUPPORT));
787 }
789 void
790 print_usage (void)
791 {
792 printf (_("Usage: "));
793 printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
794 printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
795 printf (" [-C command] [-t timeout] [-v]\n");
796 }