Code

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