Code

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