Code

cleaning help and usage + license
[nagiosplug.git] / plugins / check_procs.c
1 /******************************************************************************
2 *
3 * Nagios check_procs plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2006 nagios-plugins team
7 *
8 * Last Modified: $Date$
9 *
10 * Description:
11 *
12 * This file contains the check_procs plugin
13 *
14 * License Information:
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 *
30 * $Id$
31
32 ******************************************************************************/
34 const char *progname = "check_procs";
35 const char *revision = "$Revision$";
36 const char *copyright = "2000-2006";
37 const char *email = "nagiosplug-devel@lists.sourceforge.net";
39 #include "common.h"
40 #include "popen.h"
41 #include "utils.h"
43 #include <pwd.h>
45 int process_arguments (int, char **);
46 int validate_arguments (void);
47 int check_thresholds (int);
48 int convert_to_seconds (char *); 
49 void print_help (void);
50 void print_usage (void);
52 int wmax = -1;
53 int cmax = -1;
54 int wmin = -1;
55 int cmin = -1;
57 int options = 0; /* bitmask of filter criteria to test against */
58 #define ALL 1
59 #define STAT 2
60 #define PPID 4
61 #define USER 8
62 #define PROG 16
63 #define ARGS 32
64 #define VSZ  64
65 #define RSS  128
66 #define PCPU 256
67 #define ELAPSED 512
68 /* Different metrics */
69 char *metric_name;
70 enum metric {
71         METRIC_PROCS,
72         METRIC_VSZ,
73         METRIC_RSS,
74         METRIC_CPU,
75         METRIC_ELAPSED
76 };
77 enum metric metric = METRIC_PROCS;
79 int verbose = 0;
80 int uid;
81 pid_t ppid;
82 int vsz;
83 int rss;
84 float pcpu;
85 char *statopts;
86 char *prog;
87 char *args;
88 char *fmt;
89 char *fails;
90 char tmp[MAX_INPUT_BUFFER];
94 int
95 main (int argc, char **argv)
96 {
97         char *input_buffer;
98         char *input_line;
99         char *procprog;
101         pid_t mypid = 0;
102         int procuid = 0;
103         pid_t procpid = 0;
104         pid_t procppid = 0;
105         int procvsz = 0;
106         int procrss = 0;
107         int procseconds = 0;
108         float procpcpu = 0;
109         char procstat[8];
110         char procetime[MAX_INPUT_BUFFER] = { '\0' };
111         char *procargs;
113         const char *zombie = "Z";
115         int resultsum = 0; /* bitmask of the filter criteria met by a process */
116         int found = 0; /* counter for number of lines returned in `ps` output */
117         int procs = 0; /* counter for number of processes meeting filter criteria */
118         int pos; /* number of spaces before 'args' in `ps` output */
119         int cols; /* number of columns in ps output */
120         int expected_cols = PS_COLS - 1;
121         int warn = 0; /* number of processes in warn state */
122         int crit = 0; /* number of processes in crit state */
123         int i = 0;
124         int result = STATE_UNKNOWN;
126         setlocale (LC_ALL, "");
127         bindtextdomain (PACKAGE, LOCALEDIR);
128         textdomain (PACKAGE);
129         setlocale(LC_NUMERIC, "POSIX");
131         input_buffer = malloc (MAX_INPUT_BUFFER);
132         procprog = malloc (MAX_INPUT_BUFFER);
134         asprintf (&metric_name, "PROCS");
135         metric = METRIC_PROCS;
137         if (process_arguments (argc, argv) == ERROR)
138                 usage4 (_("Could not parse arguments"));
140         /* get our pid */
141         mypid = getpid();
143         /* Set signal handling and alarm timeout */
144         if (signal (SIGALRM, popen_timeout_alarm_handler) == SIG_ERR) {
145                 usage4 (_("Cannot catch SIGALRM"));
146         }
147         alarm (timeout_interval);
149         if (verbose >= 2)
150                 printf (_("CMD: %s\n"), PS_COMMAND);
152         child_process = spopen (PS_COMMAND);
153         if (child_process == NULL) {
154                 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
155                 return STATE_UNKNOWN;
156         }
158         child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
159         if (child_stderr == NULL)
160                 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
162         /* flush first line */
163         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
164         while ( input_buffer[strlen(input_buffer)-1] != '\n' )
165                 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
167         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
168                 asprintf (&input_line, "%s", input_buffer);
169                 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
170                         fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
171                         asprintf (&input_line, "%s%s", input_line, input_buffer);
172                 }
174                 if (verbose >= 3)
175                         printf ("%s", input_line);
177                 strcpy (procprog, "");
178                 asprintf (&procargs, "%s", "");
180                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
182                 /* Zombie processes do not give a procprog command */
183                 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
184                         cols = expected_cols;
185                 }
186                 if ( cols >= expected_cols ) {
187                         resultsum = 0;
188                         asprintf (&procargs, "%s", input_line + pos);
189                         strip (procargs);
191                         /* Some ps return full pathname for command. This removes path */
192                         procprog = basename(procprog);
194                         /* we need to convert the elapsed time to seconds */
195                         procseconds = convert_to_seconds(procetime);
197                         if (verbose >= 3)
198                                 printf ("%d %d %d %d %d %d %.2f %s %s %s %s\n", 
199                                         procs, procuid, procvsz, procrss,
200                                         procpid, procppid, procpcpu, procstat, 
201                                         procetime, procprog, procargs);
203                         /* Ignore self */
204                         if (mypid == procpid) continue;
206                         if ((options & STAT) && (strstr (statopts, procstat)))
207                                 resultsum |= STAT;
208                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
209                                 resultsum |= ARGS;
210                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
211                                 resultsum |= PROG;
212                         if ((options & PPID) && (procppid == ppid))
213                                 resultsum |= PPID;
214                         if ((options & USER) && (procuid == uid))
215                                 resultsum |= USER;
216                         if ((options & VSZ)  && (procvsz >= vsz))
217                                 resultsum |= VSZ;
218                         if ((options & RSS)  && (procrss >= rss))
219                                 resultsum |= RSS;
220                         if ((options & PCPU)  && (procpcpu >= pcpu))
221                                 resultsum |= PCPU;
223                         found++;
225                         /* Next line if filters not matched */
226                         if (!(options == resultsum || options == ALL))
227                                 continue;
229                         procs++;
231                         if (metric == METRIC_VSZ)
232                                 i = check_thresholds (procvsz);
233                         else if (metric == METRIC_RSS)
234                                 i = check_thresholds (procrss);
235                         /* TODO? float thresholds for --metric=CPU */
236                         else if (metric == METRIC_CPU)
237                                 i = check_thresholds ((int)procpcpu); 
238                         else if (metric == METRIC_ELAPSED)
239                                 i = check_thresholds (procseconds);
241                         if (metric != METRIC_PROCS) {
242                                 if (i == STATE_WARNING) {
243                                         warn++;
244                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
245                                         result = max_state (result, i);
246                                 }
247                                 if (i == STATE_CRITICAL) {
248                                         crit++;
249                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
250                                         result = max_state (result, i);
251                                 }
252                         }
253                 } 
254                 /* This should not happen */
255                 else if (verbose) {
256                         printf(_("Not parseable: %s"), input_buffer);
257                 }
258         }
260         /* If we get anything on STDERR, at least set warning */
261         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
262                 if (verbose)
263                         printf ("STDERR: %s", input_buffer);
264                 result = max_state (result, STATE_WARNING);
265                 printf (_("System call sent warnings to stderr\n"));
266         }
267         
268         (void) fclose (child_stderr);
270         /* close the pipe */
271         if (spclose (child_process)) {
272                 printf (_("System call returned nonzero status\n"));
273                 result = max_state (result, STATE_WARNING);
274         }
276         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
277                 printf (_("Unable to read output\n"));
278                 return result;
279         }
281         if ( result == STATE_UNKNOWN ) 
282                 result = STATE_OK;
284         /* Needed if procs found, but none match filter */
285         if ( metric == METRIC_PROCS ) {
286                 result = max_state (result, check_thresholds (procs) );
287         }
289         if ( result == STATE_OK ) {
290                 printf ("%s %s: ", metric_name, _("OK"));
291         } else if (result == STATE_WARNING) {
292                 printf ("%s %s: ", metric_name, _("WARNING"));
293                 if ( metric != METRIC_PROCS ) {
294                         printf (_("%d warn out of "), warn);
295                 }
296         } else if (result == STATE_CRITICAL) {
297                 printf ("%s %s: ", metric_name, _("CRITICAL"));
298                 if (metric != METRIC_PROCS) {
299                         printf (_("%d crit, %d warn out of "), crit, warn);
300                 }
301         } 
302         printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
303         
304         if (strcmp(fmt,"") != 0) {
305                 printf (_(" with %s"), fmt);
306         }
308         if ( verbose >= 1 && strcmp(fails,"") )
309                 printf (" [%s]", fails);
311         printf ("\n");
312         return result;
317 /* process command-line arguments */
318 int
319 process_arguments (int argc, char **argv)
321         int c = 1;
322         char *user;
323         struct passwd *pw;
324         int option = 0;
325         static struct option longopts[] = {
326                 {"warning", required_argument, 0, 'w'},
327                 {"critical", required_argument, 0, 'c'},
328                 {"metric", required_argument, 0, 'm'},
329                 {"timeout", required_argument, 0, 't'},
330                 {"status", required_argument, 0, 's'},
331                 {"ppid", required_argument, 0, 'p'},
332                 {"command", required_argument, 0, 'C'},
333                 {"vsz", required_argument, 0, 'z'},
334                 {"rss", required_argument, 0, 'r'},
335                 {"pcpu", required_argument, 0, 'P'},
336                 {"elapsed", required_argument, 0, 'e'},
337                 {"argument-array", required_argument, 0, 'a'},
338                 {"help", no_argument, 0, 'h'},
339                 {"version", no_argument, 0, 'V'},
340                 {"verbose", no_argument, 0, 'v'},
341                 {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                         usage2 (_("Unknown argument"), optarg);
358                 case 'h':                                                                       /* help */
359                         print_help ();
360                         exit (STATE_OK);
361                 case 'V':                                                                       /* version */
362                         print_revision (progname, revision);
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 %s 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 %s 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 'r':                                       /* RSS */
450                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
451                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
452                                 options |= RSS;
453                                 break;
454                         }
455                         usage4 (_("RSS must be an integer!"));
456                 case 'z':                                       /* VSZ */
457                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
458                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
459                                 options |= VSZ;
460                                 break;
461                         }
462                         usage4 (_("VSZ must be an integer!"));
463                 case 'P':                                       /* PCPU */
464                         /* TODO: -P 1.5.5 is accepted */
465                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
466                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
467                                 options |= PCPU;
468                                 break;
469                         }
470                         usage4 (_("PCPU must be a float!"));
471                 case 'm':
472                         asprintf (&metric_name, "%s", optarg);
473                         if ( strcmp(optarg, "PROCS") == 0) {
474                                 metric = METRIC_PROCS;
475                                 break;
476                         } 
477                         else if ( strcmp(optarg, "VSZ") == 0) {
478                                 metric = METRIC_VSZ;
479                                 break;
480                         } 
481                         else if ( strcmp(optarg, "RSS") == 0 ) {
482                                 metric = METRIC_RSS;
483                                 break;
484                         }
485                         else if ( strcmp(optarg, "CPU") == 0 ) {
486                                 metric = METRIC_CPU;
487                                 break;
488                         }
489                         else if ( strcmp(optarg, "ELAPSED") == 0) {
490                                 metric = METRIC_ELAPSED;
491                                 break;
492                         }
493                                 
494                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
495                 case 'v':                                                                       /* command */
496                         verbose++;
497                         break;
498                 }
499         }
501         c = optind;
502         if (wmax == -1 && argv[c])
503                 wmax = atoi (argv[c++]);
504         if (cmax == -1 && argv[c])
505                 cmax = atoi (argv[c++]);
506         if (statopts == NULL && argv[c]) {
507                 asprintf (&statopts, "%s", argv[c++]);
508                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
509                 options |= STAT;
510         }
512         return validate_arguments ();
517 int
518 validate_arguments ()
521         if (wmax >= 0 && wmin == -1)
522                 wmin = 0;
523         if (cmax >= 0 && cmin == -1)
524                 cmin = 0;
525         if (wmax >= wmin && cmax >= cmin) {     /* standard ranges */
526                 if (wmax > cmax && cmax != -1) {
527                         printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
528                         return ERROR;
529                 }
530                 if (cmin > wmin && wmin != -1) {
531                         printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
532                         return ERROR;
533                 }
534         }
536 /*      if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
537 /*              printf ("At least one threshold must be set\n"); */
538 /*              return ERROR; */
539 /*      } */
541         if (options == 0)
542                 options = ALL;
544         if (statopts==NULL)
545                 statopts = strdup("");
547         if (prog==NULL)
548                 prog = strdup("");
550         if (args==NULL)
551                 args = strdup("");
553         if (fmt==NULL)
554                 fmt = strdup("");
556         if (fails==NULL)
557                 fails = strdup("");
559         return options;
564 /* Check thresholds against value */
565 int
566 check_thresholds (int value)
568         if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
569                 return OK;
570         }
571         else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
572                 if (value > cmax && value < cmin)
573                         return STATE_CRITICAL;
574         }
575         else if (cmax >= 0 && value > cmax) {
576                 return STATE_CRITICAL;
577         }
578         else if (cmin >= 0 && value < cmin) {
579                 return STATE_CRITICAL;
580         }
582         if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
583                 if (value > wmax && value < wmin) {
584                         return STATE_WARNING;
585                 }
586         }
587         else if (wmax >= 0 && value > wmax) {
588                 return STATE_WARNING;
589         }
590         else if (wmin >= 0 && value < wmin) {
591                 return STATE_WARNING;
592         }
593         return STATE_OK;
597 /* convert the elapsed time to seconds */
598 int
599 convert_to_seconds(char *etime) {
601         char *ptr;
602         int total;
604         int hyphcnt;
605         int coloncnt;
606         int days;
607         int hours;
608         int minutes;
609         int seconds;
611         hyphcnt = 0;
612         coloncnt = 0;
613         days = 0;
614         hours = 0;
615         minutes = 0;
616         seconds = 0;
618         for (ptr = etime; *ptr != '\0'; ptr++) {
619         
620                 if (*ptr == '-') {
621                         hyphcnt++;
622                         continue;
623                 }
624                 if (*ptr == ':') {
625                         coloncnt++;
626                         continue;
627                 }
628         }
630         if (hyphcnt > 0) {
631                 sscanf(etime, "%d-%d:%d:%d",
632                                 &days, &hours, &minutes, &seconds);
633                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
634                  * elapsed times for some reason */
635                 if (days == 49710) {
636                         return 0;
637                 }
638         } else {
639                 if (coloncnt == 2) {
640                         sscanf(etime, "%d:%d:%d",
641                                 &hours, &minutes, &seconds);
642                 } else if (coloncnt == 1) {
643                         sscanf(etime, "%d:%d",
644                                 &minutes, &seconds);
645                 }
646         }
648         total = (days * 86400) +
649                 (hours * 3600) +
650                 (minutes * 60) +
651                 seconds;
653         if (verbose >= 3 && metric == METRIC_ELAPSED) {
654                         printf("seconds: %d\n", total);
655         }
656         return total;
660 void
661 print_help (void)
663         print_revision (progname, revision);
665         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>");
666         printf (COPYRIGHT, copyright, email);
668         printf(_("\
669 Checks all processes and generates WARNING or CRITICAL states if the specified\n\
670 metric is outside the required threshold ranges. The metric defaults to number\n\
671 of processes.  Search filters can be applied to limit the processes to check.\n\n"));
673         print_usage ();
675         printf(_("\n\
676 Required Arguments:\n\
677  -w, --warning=RANGE\n\
678    Generate warning state if metric is outside this range\n\
679  -c, --critical=RANGE\n\
680    Generate critical state if metric is outside this range\n"));
682         printf(_("\n\
683 Optional Arguments:\n\
684  -m, --metric=TYPE\n\
685    Check thresholds against metric. Valid types:\n\
686    PROCS   - number of processes (default)\n\
687    VSZ     - virtual memory size\n\
688    RSS     - resident set memory size\n\
689    CPU     - percentage cpu\n"));
690 /* only linux etime is support currently */
691 #if defined( __linux__ )
692         printf(_("\
693    ELAPSED - time elapsed in seconds\n"));
694 #endif /* defined(__linux__) */
695         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
697         printf(_("\
698  -v, --verbose\n\
699    Extra information. Up to 3 verbosity levels\n"));
701         printf(_("\n\
702 Optional Filters:\n\
703  -s, --state=STATUSFLAGS\n\
704    Only scan for processes that have, in the output of `ps`, one or\n\
705    more of the status flags you specify (for example R, Z, S, RS,\n\
706    RSZDT, plus others based on the output of your 'ps' command).\n\
707  -p, --ppid=PPID\n\
708    Only scan for children of the parent process ID indicated.\n\
709  -z, --vsz=VSZ\n\
710    Only scan for processes with vsz higher than indicated.\n\
711  -r, --rss=RSS\n\
712    Only scan for processes with rss higher than indicated.\n"));
714         printf(_("\
715  -P, --pcpu=PCPU\n\
716    Only scan for processes with pcpu higher than indicated.\n\
717  -u, --user=USER\n\
718    Only scan for processes with user name or ID indicated.\n\
719  -a, --argument-array=STRING\n\
720    Only scan for processes with args that contain STRING.\n\
721  -C, --command=COMMAND\n\
722    Only scan for exact matches of COMMAND (without path).\n"));
724         printf(_("\n\
725 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
726 specified 'max:min', a warning status will be generated if the\n\
727 count is inside the specified range\n\n"));
729         printf(_("\
730 This plugin checks the number of currently running processes and\n\
731 generates WARNING or CRITICAL states if the process count is outside\n\
732 the specified threshold ranges. The process count can be filtered by\n\
733 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
734 be the total number of running processes\n\n"));
736         printf(_("\
737 Examples:\n\
738  check_procs -w 2:2 -c 2:1024 -C portsentry\n\
739    Warning if not two processes with command name portsentry. Critical\n\
740    if < 2 or > 1024 processes\n\n\
741  check_procs -w 10 -a '/usr/local/bin/perl' -u root\n\
742    Warning alert if > 10 processes with command arguments containing \n\
743    '/usr/local/bin/perl' and owned by root\n\n\
744  check_procs -w 50000 -c 100000 --metric=VSZ\n\
745    Alert if vsz of any processes over 50K or 100K\n\
746  check_procs -w 10 -c 20 --metric=CPU\n\
747    Alert if cpu of any processes over 10%% or 20%%\n\n"));
749         printf (_(UT_SUPPORT));
752 void
753 print_usage (void)
755   printf (_("Usage:"));
756         printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
757   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
758   printf (" [-C command] [-t timeout] [-v]\n");