Code

check_procs captures stderr and adds to plugin output. This is
[nagiosplug.git] / plugins / check_procs.c
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)
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);
300         
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;
314 /* process command-line arguments */
315 int
316 process_arguments (int argc, char **argv)
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                         }
504                                 
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 ();
531 int
532 validate_arguments ()
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;
578 /* Check thresholds against value */
579 int
580 check_thresholds (int value)
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;
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++) {
633         
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;
674 void
675 print_help (void)
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));
767 void
768 print_usage (void)
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");