Code

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