Code

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