Code

b866ac2cae1c98b4e92f9a6a885589a07b411053
[nagiosplug.git] / plugins / check_procs.c
1 /******************************************************************************
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; either version 2 of the License, or
6  (at your option) any later version.
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  GNU General Public License for more details.
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  $Id$
18  
19 ******************************************************************************/
21 const char *progname = "check_procs";
22 const char *revision = "$Revision$";
23 const char *copyright = "2000-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "popen.h"
28 #include "utils.h"
30 #include <pwd.h>
32 int process_arguments (int, char **);
33 int validate_arguments (void);
34 int check_thresholds (int);
35 int convert_to_seconds (char *); 
36 void print_help (void);
37 void print_usage (void);
39 int wmax = -1;
40 int cmax = -1;
41 int wmin = -1;
42 int cmin = -1;
44 int options = 0; /* bitmask of filter criteria to test against */
45 #define ALL 1
46 #define STAT 2
47 #define PPID 4
48 #define USER 8
49 #define PROG 16
50 #define ARGS 32
51 #define VSZ  64
52 #define RSS  128
53 #define PCPU 256
54 #define ELAPSED 512
55 /* Different metrics */
56 char *metric_name;
57 enum metric {
58         METRIC_PROCS,
59         METRIC_VSZ,
60         METRIC_RSS,
61         METRIC_CPU,
62         METRIC_ELAPSED
63 };
64 enum metric metric = METRIC_PROCS;
66 int verbose = 0;
67 int uid;
68 int ppid;
69 int vsz;
70 int rss;
71 float pcpu;
72 char *statopts;
73 char *prog;
74 char *args;
75 char *fmt;
76 char *fails;
77 char tmp[MAX_INPUT_BUFFER];
81 int
82 main (int argc, char **argv)
83 {
84         char *input_buffer;
85         char *input_line;
86         char *procprog;
88         pid_t mypid = 0;
89         int procuid = 0;
90         int procpid = 0;
91         int procppid = 0;
92         int procvsz = 0;
93         int procrss = 0;
94         int procseconds = 0;
95         float procpcpu = 0;
96         char procstat[8];
97         char procetime[MAX_INPUT_BUFFER] = { '\0' };
98         char *procargs;
99 #ifdef HAVE_BASENAME
100         char *temp_string;
101 #endif
103         const char *zombie = "Z";
105         int resultsum = 0; /* bitmask of the filter criteria met by a process */
106         int found = 0; /* counter for number of lines returned in `ps` output */
107         int procs = 0; /* counter for number of processes meeting filter criteria */
108         int pos; /* number of spaces before 'args' in `ps` output */
109         int cols; /* number of columns in ps output */
110         int expected_cols = PS_COLS - 1;
111         int warn = 0; /* number of processes in warn state */
112         int crit = 0; /* number of processes in crit state */
113         int i = 0;
114         int result = STATE_UNKNOWN;
116         setlocale (LC_ALL, "");
117         bindtextdomain (PACKAGE, LOCALEDIR);
118         textdomain (PACKAGE);
119         setlocale(LC_NUMERIC, "POSIX");
121         input_buffer = malloc (MAX_INPUT_BUFFER);
122         procprog = malloc (MAX_INPUT_BUFFER);
124         asprintf (&metric_name, "PROCS");
125         metric = METRIC_PROCS;
127         if (process_arguments (argc, argv) == ERROR)
128                 usage4 (_("Could not parse arguments"));
130         /* get our pid */
131         mypid = getpid();
133         /* Set signal handling and alarm timeout */
134         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
135                 usage4 (_("Cannot catch SIGALRM"));
136         }
137         alarm (timeout_interval);
139         if (verbose >= 2)
140                 printf (_("CMD: %s\n"), PS_COMMAND);
142         child_process = spopen (PS_COMMAND);
143         if (child_process == NULL) {
144                 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
145                 return STATE_UNKNOWN;
146         }
148         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
149         if (child_stderr == NULL)
150                 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
152         /* flush first line */
153         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
154         while ( input_buffer[strlen(input_buffer)-1] != '\n' )
155                 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
157         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
158                 asprintf (&input_line, "%s", input_buffer);
159                 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
160                         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
161                         asprintf (&input_line, "%s%s", input_line, input_buffer);
162                 }
164                 if (verbose >= 3)
165                         printf ("%s", input_line);
167                 strcpy (procprog, "");
168                 asprintf (&procargs, "%s", "");
170                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
172                 /* Zombie processes do not give a procprog command */
173                 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
174                         cols = expected_cols;
175                 }
176                 if ( cols >= expected_cols ) {
177                         resultsum = 0;
178                         asprintf (&procargs, "%s", input_line + pos);
179                         strip (procargs);
181                         /* Some ps return full pathname for command. This removes path */
182 #ifdef HAVE_BASENAME
183                         temp_string = strdup(procprog);
184                         procprog = basename(temp_string);
185 #endif /* HAVE_BASENAME */
187                         /* we need to convert the elapsed time to seconds */
188                         procseconds = convert_to_seconds(procetime);
190                         if (verbose >= 3)
191                                 printf ("%d %d %d %d %d %d %.2f %s %s %s %s\n", 
192                                         procs, procuid, procvsz, procrss,
193                                         procpid, procppid, procpcpu, procstat, 
194                                         procetime, procprog, procargs);
196                         /* Ignore self */
197                         if (mypid == procpid) continue;
199                         if ((options & STAT) && (strstr (statopts, procstat)))
200                                 resultsum |= STAT;
201                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
202                                 resultsum |= ARGS;
203                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
204                                 resultsum |= PROG;
205                         if ((options & PPID) && (procppid == ppid))
206                                 resultsum |= PPID;
207                         if ((options & USER) && (procuid == uid))
208                                 resultsum |= USER;
209                         if ((options & VSZ)  && (procvsz >= vsz))
210                                 resultsum |= VSZ;
211                         if ((options & RSS)  && (procrss >= rss))
212                                 resultsum |= RSS;
213                         if ((options & PCPU)  && (procpcpu >= pcpu))
214                                 resultsum |= PCPU;
216                         found++;
218                         /* Next line if filters not matched */
219                         if (!(options == resultsum || options == ALL))
220                                 continue;
222                         procs++;
224                         if (metric == METRIC_VSZ)
225                                 i = check_thresholds (procvsz);
226                         else if (metric == METRIC_RSS)
227                                 i = check_thresholds (procrss);
228                         /* TODO? float thresholds for --metric=CPU */
229                         else if (metric == METRIC_CPU)
230                                 i = check_thresholds ((int)procpcpu); 
231                         else if (metric == METRIC_ELAPSED)
232                                 i = check_thresholds (procseconds);
234                         if (metric != METRIC_PROCS) {
235                                 if (i == STATE_WARNING) {
236                                         warn++;
237                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
238                                         result = max_state (result, i);
239                                 }
240                                 if (i == STATE_CRITICAL) {
241                                         crit++;
242                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
243                                         result = max_state (result, i);
244                                 }
245                         }
246                 } 
247                 /* This should not happen */
248                 else if (verbose) {
249                         printf(_("Not parseable: %s"), input_buffer);
250                 }
251         }
253         /* If we get anything on STDERR, at least set warning */
254         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
255                 if (verbose)
256                         printf ("STDERR: %s", input_buffer);
257                 result = max_state (result, STATE_WARNING);
258                 printf (_("System call sent warnings to stderr\n"));
259         }
260         
261         (void) fclose (child_stderr);
263         /* close the pipe */
264         if (spclose (child_process)) {
265                 printf (_("System call returned nonzero status\n"));
266                 result = max_state (result, STATE_WARNING);
267         }
269         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
270                 printf (_("Unable to read output\n"));
271                 return result;
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         static struct option longopts[] = {
319                 {"warning", required_argument, 0, 'w'},
320                 {"critical", required_argument, 0, 'c'},
321                 {"metric", required_argument, 0, 'm'},
322                 {"timeout", required_argument, 0, 't'},
323                 {"status", required_argument, 0, 's'},
324                 {"ppid", required_argument, 0, 'p'},
325                 {"command", required_argument, 0, 'C'},
326                 {"vsz", required_argument, 0, 'z'},
327                 {"rss", required_argument, 0, 'r'},
328                 {"pcpu", required_argument, 0, 'P'},
329                 {"elapsed", required_argument, 0, 'e'},
330                 {"argument-array", required_argument, 0, 'a'},
331                 {"help", no_argument, 0, 'h'},
332                 {"version", no_argument, 0, 'V'},
333                 {"verbose", no_argument, 0, 'v'},
334                 {0, 0, 0, 0}
335         };
337         for (c = 1; c < argc; c++)
338                 if (strcmp ("-to", argv[c]) == 0)
339                         strcpy (argv[c], "-t");
341         while (1) {
342                 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", 
343                         longopts, &option);
345                 if (c == -1 || c == EOF)
346                         break;
348                 switch (c) {
349                 case '?':                                                                       /* help */
350                         usage2 (_("Unknown argument"), optarg);
351                 case 'h':                                                                       /* help */
352                         print_help ();
353                         exit (STATE_OK);
354                 case 'V':                                                                       /* version */
355                         print_revision (progname, revision);
356                         exit (STATE_OK);
357                 case 't':                                                                       /* timeout period */
358                         if (!is_integer (optarg))
359                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
360                         else
361                                 timeout_interval = atoi (optarg);
362                         break;
363                 case 'c':                                                                       /* critical threshold */
364                         if (is_integer (optarg))
365                                 cmax = atoi (optarg);
366                         else if (sscanf (optarg, ":%d", &cmax) == 1)
367                                 break;
368                         else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
369                                 break;
370                         else if (sscanf (optarg, "%d:", &cmin) == 1)
371                                 break;
372                         else
373                                 usage4 (_("Critical Process Count must be an integer!"));
374                         break;                                                   
375                 case 'w':                                                                       /* warning threshold */
376                         if (is_integer (optarg))
377                                 wmax = atoi (optarg);
378                         else if (sscanf (optarg, ":%d", &wmax) == 1)
379                                 break;
380                         else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
381                                 break;
382                         else if (sscanf (optarg, "%d:", &wmin) == 1)
383                                 break;
384                         else
385                                 usage4 (_("Warning Process Count must be an integer!"));
386                         break;
387                 case 'p':                                                                       /* process id */
388                         if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
389                                 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
390                                 options |= PPID;
391                                 break;
392                         }
393                         usage4 (_("Parent Process ID must be an integer!"));
394                 case 's':                                                                       /* status */
395                         if (statopts)
396                                 break;
397                         else
398                                 statopts = optarg;
399                         asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
400                         options |= STAT;
401                         break;
402                 case 'u':                                                                       /* user or user id */
403                         if (is_integer (optarg)) {
404                                 uid = atoi (optarg);
405                                 pw = getpwuid ((uid_t) uid);
406                                 /*  check to be sure user exists */
407                                 if (pw == NULL)
408                                         usage2 (_("UID %s was not found"), optarg);
409                         }
410                         else {
411                                 pw = getpwnam (optarg);
412                                 /*  check to be sure user exists */
413                                 if (pw == NULL)
414                                         usage2 (_("User name %s was not found"), optarg);
415                                 /*  then get uid */
416                                 uid = pw->pw_uid;
417                         }
418                         user = pw->pw_name;
419                         asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
420                                   uid, user);
421                         options |= USER;
422                         break;
423                 case 'C':                                                                       /* command */
424                         /* TODO: allow this to be passed in with --metric */
425                         if (prog)
426                                 break;
427                         else
428                                 prog = optarg;
429                         asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
430                                   prog);
431                         options |= PROG;
432                         break;
433                 case 'a':                                                                       /* args (full path name with args) */
434                         /* TODO: allow this to be passed in with --metric */
435                         if (args)
436                                 break;
437                         else
438                                 args = optarg;
439                         asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
440                         options |= ARGS;
441                         break;
442                 case 'r':                                       /* RSS */
443                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
444                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
445                                 options |= RSS;
446                                 break;
447                         }
448                         usage4 (_("RSS must be an integer!"));
449                 case 'z':                                       /* VSZ */
450                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
451                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
452                                 options |= VSZ;
453                                 break;
454                         }
455                         usage4 (_("VSZ must be an integer!"));
456                 case 'P':                                       /* PCPU */
457                         /* TODO: -P 1.5.5 is accepted */
458                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
459                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
460                                 options |= PCPU;
461                                 break;
462                         }
463                         usage4 (_("PCPU must be a float!"));
464                 case 'm':
465                         asprintf (&metric_name, "%s", optarg);
466                         if ( strcmp(optarg, "PROCS") == 0) {
467                                 metric = METRIC_PROCS;
468                                 break;
469                         } 
470                         else if ( strcmp(optarg, "VSZ") == 0) {
471                                 metric = METRIC_VSZ;
472                                 break;
473                         } 
474                         else if ( strcmp(optarg, "RSS") == 0 ) {
475                                 metric = METRIC_RSS;
476                                 break;
477                         }
478                         else if ( strcmp(optarg, "CPU") == 0 ) {
479                                 metric = METRIC_CPU;
480                                 break;
481                         }
482                         else if ( strcmp(optarg, "ELAPSED") == 0) {
483                                 metric = METRIC_ELAPSED;
484                                 break;
485                         }
486                                 
487                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
488                 case 'v':                                                                       /* command */
489                         verbose++;
490                         break;
491                 }
492         }
494         c = optind;
495         if (wmax == -1 && argv[c])
496                 wmax = atoi (argv[c++]);
497         if (cmax == -1 && argv[c])
498                 cmax = atoi (argv[c++]);
499         if (statopts == NULL && argv[c]) {
500                 asprintf (&statopts, "%s", argv[c++]);
501                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
502                 options |= STAT;
503         }
505         return validate_arguments ();
510 int
511 validate_arguments ()
514         if (wmax >= 0 && wmin == -1)
515                 wmin = 0;
516         if (cmax >= 0 && cmin == -1)
517                 cmin = 0;
518         if (wmax >= wmin && cmax >= cmin) {     /* standard ranges */
519                 if (wmax > cmax && cmax != -1) {
520                         printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
521                         return ERROR;
522                 }
523                 if (cmin > wmin && wmin != -1) {
524                         printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
525                         return ERROR;
526                 }
527         }
529 /*      if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
530 /*              printf ("At least one threshold must be set\n"); */
531 /*              return ERROR; */
532 /*      } */
534         if (options == 0)
535                 options = ALL;
537         if (statopts==NULL)
538                 statopts = strdup("");
540         if (prog==NULL)
541                 prog = strdup("");
543         if (args==NULL)
544                 args = strdup("");
546         if (fmt==NULL)
547                 fmt = strdup("");
549         if (fails==NULL)
550                 fails = strdup("");
552         return options;
557 /* Check thresholds against value */
558 int
559 check_thresholds (int value)
561         if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
562                 return OK;
563         }
564         else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
565                 if (value > cmax && value < cmin)
566                         return STATE_CRITICAL;
567         }
568         else if (cmax >= 0 && value > cmax) {
569                 return STATE_CRITICAL;
570         }
571         else if (cmin >= 0 && value < cmin) {
572                 return STATE_CRITICAL;
573         }
575         if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
576                 if (value > wmax && value < wmin) {
577                         return STATE_WARNING;
578                 }
579         }
580         else if (wmax >= 0 && value > wmax) {
581                 return STATE_WARNING;
582         }
583         else if (wmin >= 0 && value < wmin) {
584                 return STATE_WARNING;
585         }
586         return STATE_OK;
590 /* convert the elapsed time to seconds */
591 int
592 convert_to_seconds(char *etime) {
594         char *ptr;
595         int total;
597         int hyphcnt;
598         int coloncnt;
599         int days;
600         int hours;
601         int minutes;
602         int seconds;
604         hyphcnt = 0;
605         coloncnt = 0;
606         days = 0;
607         hours = 0;
608         minutes = 0;
609         seconds = 0;
611         for (ptr = etime; *ptr != '\0'; ptr++) {
612         
613                 if (*ptr == '-') {
614                         hyphcnt++;
615                         continue;
616                 }
617                 if (*ptr == ':') {
618                         coloncnt++;
619                         continue;
620                 }
621         }
623         if (hyphcnt > 0) {
624                 sscanf(etime, "%d-%d:%d:%d",
625                                 &days, &hours, &minutes, &seconds);
626                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
627                  * elapsed times for some reason */
628                 if (days == 49710) {
629                         return 0;
630                 }
631         } else {
632                 if (coloncnt == 2) {
633                         sscanf(etime, "%d:%d:%d",
634                                 &hours, &minutes, &seconds);
635                 } else if (coloncnt == 1) {
636                         sscanf(etime, "%d:%d",
637                                 &minutes, &seconds);
638                 }
639         }
641         total = (days * 86400) +
642                 (hours * 3600) +
643                 (minutes * 60) +
644                 seconds;
646         if (verbose >= 3 && metric == METRIC_ELAPSED) {
647                         printf("seconds: %d\n", total);
648         }
649         return total;
653 void
654 print_help (void)
656         print_revision (progname, revision);
658         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
659         printf (COPYRIGHT, copyright, email);
661         printf(_("\
662 Checks all processes and generates WARNING or CRITICAL states if the specified\n\
663 metric is outside the required threshold ranges. The metric defaults to number\n\
664 of processes.  Search filters can be applied to limit the processes to check.\n\n"));
666         print_usage ();
668         printf(_("\n\
669 Required Arguments:\n\
670  -w, --warning=RANGE\n\
671    Generate warning state if metric is outside this range\n\
672  -c, --critical=RANGE\n\
673    Generate critical state if metric is outside this range\n"));
675         printf(_("\n\
676 Optional Arguments:\n\
677  -m, --metric=TYPE\n\
678    Check thresholds against metric. Valid types:\n\
679    PROCS   - number of processes (default)\n\
680    VSZ     - virtual memory size\n\
681    RSS     - resident set memory size\n\
682    CPU     - percentage cpu\n"));
683 /* only linux etime is support currently */
684 #if defined( __linux__ )
685         printf(_("\
686    ELAPSED - time elapsed in seconds\n"));
687 #endif /* defined(__linux__) */
688         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
690         printf(_("\
691  -v, --verbose\n\
692    Extra information. Up to 3 verbosity levels\n"));
694         printf(_("\n\
695 Optional Filters:\n\
696  -s, --state=STATUSFLAGS\n\
697    Only scan for processes that have, in the output of `ps`, one or\n\
698    more of the status flags you specify (for example R, Z, S, RS,\n\
699    RSZDT, plus others based on the output of your 'ps' command).\n\
700  -p, --ppid=PPID\n\
701    Only scan for children of the parent process ID indicated.\n\
702  -z, --vsz=VSZ\n\
703    Only scan for processes with vsz higher than indicated.\n\
704  -r, --rss=RSS\n\
705    Only scan for processes with rss higher than indicated.\n"));
707         printf(_("\
708  -P, --pcpu=PCPU\n\
709    Only scan for processes with pcpu higher than indicated.\n\
710  -u, --user=USER\n\
711    Only scan for processes with user name or ID indicated.\n\
712  -a, --argument-array=STRING\n\
713    Only scan for processes with args that contain STRING.\n\
714  -C, --command=COMMAND\n\
715    Only scan for exact matches of COMMAND (without path).\n"));
717         printf(_("\n\
718 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
719 specified 'max:min', a warning status will be generated if the\n\
720 count is inside the specified range\n\n"));
722         printf(_("\
723 This plugin checks the number of currently running processes and\n\
724 generates WARNING or CRITICAL states if the process count is outside\n\
725 the specified threshold ranges. The process count can be filtered by\n\
726 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
727 be the total number of running processes\n\n"));
729         printf(_("\
730 Examples:\n\
731  check_procs -w 2:2 -c 2:1024 -C portsentry\n\
732    Warning if not two processes with command name portsentry. Critical\n\
733    if < 2 or > 1024 processes\n\n\
734  check_procs -w 10 -a '/usr/local/bin/perl' -u root\n\
735    Warning alert if > 10 processes with command arguments containing \n\
736    '/usr/local/bin/perl' and owned by root\n\n\
737  check_procs -w 50000 -c 100000 --metric=VSZ\n\
738    Alert if vsz of any processes over 50K or 100K\n\
739  check_procs -w 10 -c 20 --metric=CPU\n\
740    Alert if cpu of any processes over 10%% or 20%%\n\n"));
742         printf (_(UT_SUPPORT));
745 void
746 print_usage (void)
748         printf ("\
749 Usage: %s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n\
750                   [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n\
751                   [-C command] [-t timeout] [-v]\n", progname);