Code

check_procs: Use the range/threshold support functions from libnagiosplug.
[nagiosplug.git] / plugins / check_procs.c
1 /*****************************************************************************
2
3 * Nagios check_procs plugin
4
5 * License: GPL
6 * Copyright (c) 2000-2008 Nagios Plugins Development Team
7
8 * Description:
9
10 * This file contains the check_procs plugin
11
12 * Checks all processes and generates WARNING or CRITICAL states if the
13 * specified metric is outside the required threshold ranges. The metric
14 * defaults to number of processes.  Search filters can be applied to limit
15 * the processes to check.
16
17
18 * This program is free software: you can redistribute it and/or modify
19 * it under the terms of the GNU General Public License as published by
20 * the Free Software Foundation, either version 3 of the License, or
21 * (at your option) any later version.
22
23 * This program is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
26 * GNU General Public License for more details.
27
28 * You should have received a copy of the GNU General Public License
29 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
30
31
32 *****************************************************************************/
34 const char *progname = "check_procs";
35 const char *program_name = "check_procs";  /* Required for coreutils libs */
36 const char *copyright = "2000-2008";
37 const char *email = "nagiosplug-devel@lists.sourceforge.net";
39 #include "common.h"
40 #include "utils.h"
41 #include "utils_cmd.h"
42 #include "regex.h"
44 #include <pwd.h>
46 int process_arguments (int, char **);
47 int validate_arguments (void);
48 int convert_to_seconds (char *); 
49 void print_help (void);
50 void print_usage (void);
52 char *warning_range = NULL;
53 char *critical_range = NULL;
54 thresholds *procs_thresholds = NULL;
56 int options = 0; /* bitmask of filter criteria to test against */
57 #define ALL 1
58 #define STAT 2
59 #define PPID 4
60 #define USER 8
61 #define PROG 16
62 #define ARGS 32
63 #define VSZ  64
64 #define RSS  128
65 #define PCPU 256
66 #define ELAPSED 512
67 #define EREG_ARGS 1024
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 *input_filename = NULL;
89 regex_t re_args;
90 char *fmt;
91 char *fails;
92 char tmp[MAX_INPUT_BUFFER];
94 FILE *ps_input = NULL;
97 int
98 main (int argc, char **argv)
99 {
100         char *input_buffer;
101         char *input_line;
102         char *procprog;
104         pid_t mypid = 0;
105         int procuid = 0;
106         pid_t procpid = 0;
107         pid_t procppid = 0;
108         int procvsz = 0;
109         int procrss = 0;
110         int procseconds = 0;
111         float procpcpu = 0;
112         char procstat[8];
113         char procetime[MAX_INPUT_BUFFER] = { '\0' };
114         char *procargs;
116         const char *zombie = "Z";
118         int resultsum = 0; /* bitmask of the filter criteria met by a process */
119         int found = 0; /* counter for number of lines returned in `ps` output */
120         int procs = 0; /* counter for number of processes meeting filter criteria */
121         int pos; /* number of spaces before 'args' in `ps` output */
122         int cols; /* number of columns in ps output */
123         int expected_cols = PS_COLS - 1;
124         int warn = 0; /* number of processes in warn state */
125         int crit = 0; /* number of processes in crit state */
126         int i = 0, j = 0;
127         int result = STATE_UNKNOWN;
128         output chld_out, chld_err;
130         setlocale (LC_ALL, "");
131         bindtextdomain (PACKAGE, LOCALEDIR);
132         textdomain (PACKAGE);
133         setlocale(LC_NUMERIC, "POSIX");
135         input_buffer = malloc (MAX_INPUT_BUFFER);
136         procprog = malloc (MAX_INPUT_BUFFER);
138         asprintf (&metric_name, "PROCS");
139         metric = METRIC_PROCS;
141         /* Parse extra opts if any */
142         argv=np_extra_opts (&argc, argv, progname);
144         if (process_arguments (argc, argv) == ERROR)
145                 usage4 (_("Could not parse arguments"));
147         /* get our pid */
148         mypid = getpid();
150         /* Set signal handling and alarm timeout */
151         if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
152                 die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
153         }
154         (void) alarm ((unsigned) timeout_interval);
156         if (verbose >= 2)
157                 printf (_("CMD: %s\n"), PS_COMMAND);
159         if (input_filename == NULL) {
160                 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
161                 if (chld_err.lines > 0) {
162                         printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
163                         exit(STATE_WARNING);
164                 }
165         } else {
166                 result = cmd_file_read( input_filename, &chld_out, 0);
167         }
169         /* flush first line: j starts at 1 */
170         for (j = 1; j < chld_out.lines; j++) {
171                 input_line = chld_out.line[j];
173                 if (verbose >= 3)
174                         printf ("%s", input_line);
176                 strcpy (procprog, "");
177                 asprintf (&procargs, "%s", "");
179                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
181                 /* Zombie processes do not give a procprog command */
182                 if ( cols < expected_cols && strstr(procstat, zombie) ) {
183                         cols = expected_cols;
184                 }
185                 if ( cols >= expected_cols ) {
186                         resultsum = 0;
187                         asprintf (&procargs, "%s", input_line + pos);
188                         strip (procargs);
190                         /* Some ps return full pathname for command. This removes path */
191                         strcpy(procprog, base_name(procprog));
193                         /* we need to convert the elapsed time to seconds */
194                         procseconds = convert_to_seconds(procetime);
196                         if (verbose >= 3)
197                                 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
198                                         procs, procuid, procvsz, procrss,
199                                         procpid, procppid, procpcpu, procstat, 
200                                         procetime, procprog, procargs);
202                         /* Ignore self */
203                         if (mypid == procpid) continue;
205                         if ((options & STAT) && (strstr (statopts, procstat)))
206                                 resultsum |= STAT;
207                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
208                                 resultsum |= ARGS;
209                         if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
210                                 resultsum |= EREG_ARGS;
211                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
212                                 resultsum |= PROG;
213                         if ((options & PPID) && (procppid == ppid))
214                                 resultsum |= PPID;
215                         if ((options & USER) && (procuid == uid))
216                                 resultsum |= USER;
217                         if ((options & VSZ)  && (procvsz >= vsz))
218                                 resultsum |= VSZ;
219                         if ((options & RSS)  && (procrss >= rss))
220                                 resultsum |= RSS;
221                         if ((options & PCPU)  && (procpcpu >= pcpu))
222                                 resultsum |= PCPU;
224                         found++;
226                         /* Next line if filters not matched */
227                         if (!(options == resultsum || options == ALL))
228                                 continue;
230                         procs++;
231                         if (verbose >= 2) {
232                                 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
233                                         procuid, procvsz, procrss,
234                                         procpid, procppid, procpcpu, procstat, 
235                                         procetime, procprog, procargs);
236                         }
238                         if (metric == METRIC_VSZ)
239                                 i = get_status ((double)procvsz, procs_thresholds);
240                         else if (metric == METRIC_RSS)
241                                 i = get_status ((double)procrss, procs_thresholds);
242                         /* TODO? float thresholds for --metric=CPU */
243                         else if (metric == METRIC_CPU)
244                                 i = get_status (procpcpu, procs_thresholds);
245                         else if (metric == METRIC_ELAPSED)
246                                 i = get_status ((double)procseconds, procs_thresholds);
248                         if (metric != METRIC_PROCS) {
249                                 if (i == STATE_WARNING) {
250                                         warn++;
251                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
252                                         result = max_state (result, i);
253                                 }
254                                 if (i == STATE_CRITICAL) {
255                                         crit++;
256                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
257                                         result = max_state (result, i);
258                                 }
259                         }
260                 } 
261                 /* This should not happen */
262                 else if (verbose) {
263                         printf(_("Not parseable: %s"), input_buffer);
264                 }
265         }
267         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
268                 printf (_("Unable to read output\n"));
269                 return STATE_UNKNOWN;
270         }
272         if ( result == STATE_UNKNOWN ) 
273                 result = STATE_OK;
275         /* Needed if procs found, but none match filter */
276         if ( metric == METRIC_PROCS ) {
277                 result = max_state (result, get_status ((double)procs, procs_thresholds) );
278         }
280         if ( result == STATE_OK ) {
281                 printf ("%s %s: ", metric_name, _("OK"));
282         } else if (result == STATE_WARNING) {
283                 printf ("%s %s: ", metric_name, _("WARNING"));
284                 if ( metric != METRIC_PROCS ) {
285                         printf (_("%d warn out of "), warn);
286                 }
287         } else if (result == STATE_CRITICAL) {
288                 printf ("%s %s: ", metric_name, _("CRITICAL"));
289                 if (metric != METRIC_PROCS) {
290                         printf (_("%d crit, %d warn out of "), crit, warn);
291                 }
292         } 
293         printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
294         
295         if (strcmp(fmt,"") != 0) {
296                 printf (_(" with %s"), fmt);
297         }
299         if ( verbose >= 1 && strcmp(fails,"") )
300                 printf (" [%s]", fails);
302         printf ("\n");
303         return result;
308 /* process command-line arguments */
309 int
310 process_arguments (int argc, char **argv)
312         int c = 1;
313         char *user;
314         struct passwd *pw;
315         int option = 0;
316         int err;
317         int cflags = REG_NOSUB | REG_EXTENDED;
318         char errbuf[MAX_INPUT_BUFFER];
319         char *temp_string;
320         int i=0;
321         static struct option longopts[] = {
322                 {"warning", required_argument, 0, 'w'},
323                 {"critical", required_argument, 0, 'c'},
324                 {"metric", required_argument, 0, 'm'},
325                 {"timeout", required_argument, 0, 't'},
326                 {"status", required_argument, 0, 's'},
327                 {"ppid", required_argument, 0, 'p'},
328                 {"command", required_argument, 0, 'C'},
329                 {"vsz", required_argument, 0, 'z'},
330                 {"rss", required_argument, 0, 'r'},
331                 {"pcpu", required_argument, 0, 'P'},
332                 {"elapsed", required_argument, 0, 'e'},
333                 {"argument-array", required_argument, 0, 'a'},
334                 {"help", no_argument, 0, 'h'},
335                 {"version", no_argument, 0, 'V'},
336                 {"verbose", no_argument, 0, 'v'},
337                 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
338                 {"input-file", required_argument, 0, CHAR_MAX+2},
339                 {0, 0, 0, 0}
340         };
342         for (c = 1; c < argc; c++)
343                 if (strcmp ("-to", argv[c]) == 0)
344                         strcpy (argv[c], "-t");
346         while (1) {
347                 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", 
348                         longopts, &option);
350                 if (c == -1 || c == EOF)
351                         break;
353                 switch (c) {
354                 case '?':                                                                       /* help */
355                         usage5 ();
356                 case 'h':                                                                       /* help */
357                         print_help ();
358                         exit (STATE_OK);
359                 case 'V':                                                                       /* version */
360                         print_revision (progname, NP_VERSION);
361                         exit (STATE_OK);
362                 case 't':                                                                       /* timeout period */
363                         if (!is_integer (optarg))
364                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
365                         else
366                                 timeout_interval = atoi (optarg);
367                         break;
368                 case 'c':                                                                       /* critical threshold */
369                         critical_range = optarg;
370                         break;                                                   
371                 case 'w':                                                                       /* warning threshold */
372                         warning_range = optarg;
373                         break;
374                 case 'p':                                                                       /* process id */
375                         if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
376                                 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
377                                 options |= PPID;
378                                 break;
379                         }
380                         usage4 (_("Parent Process ID must be an integer!"));
381                 case 's':                                                                       /* status */
382                         if (statopts)
383                                 break;
384                         else
385                                 statopts = optarg;
386                         asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
387                         options |= STAT;
388                         break;
389                 case 'u':                                                                       /* user or user id */
390                         if (is_integer (optarg)) {
391                                 uid = atoi (optarg);
392                                 pw = getpwuid ((uid_t) uid);
393                                 /*  check to be sure user exists */
394                                 if (pw == NULL)
395                                         usage2 (_("UID was not found"), optarg);
396                         }
397                         else {
398                                 pw = getpwnam (optarg);
399                                 /*  check to be sure user exists */
400                                 if (pw == NULL)
401                                         usage2 (_("User name was not found"), optarg);
402                                 /*  then get uid */
403                                 uid = pw->pw_uid;
404                         }
405                         user = pw->pw_name;
406                         asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
407                                   uid, user);
408                         options |= USER;
409                         break;
410                 case 'C':                                                                       /* command */
411                         /* TODO: allow this to be passed in with --metric */
412                         if (prog)
413                                 break;
414                         else
415                                 prog = optarg;
416                         asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
417                                   prog);
418                         options |= PROG;
419                         break;
420                 case 'a':                                                                       /* args (full path name with args) */
421                         /* TODO: allow this to be passed in with --metric */
422                         if (args)
423                                 break;
424                         else
425                                 args = optarg;
426                         asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
427                         options |= ARGS;
428                         break;
429                 case CHAR_MAX+1:
430                         err = regcomp(&re_args, optarg, cflags);
431                         if (err != 0) {
432                                 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
433                                 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
434                         }
435                         /* Strip off any | within the regex optarg */
436                         temp_string = strdup(optarg);
437                         while(temp_string[i]!='\0'){
438                                 if(temp_string[i]=='|')
439                                         temp_string[i]=',';
440                                 i++;
441                         }
442                         asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), temp_string);
443                         options |= EREG_ARGS;
444                         break;
445                 case 'r':                                       /* RSS */
446                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
447                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
448                                 options |= RSS;
449                                 break;
450                         }
451                         usage4 (_("RSS must be an integer!"));
452                 case 'z':                                       /* VSZ */
453                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
454                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
455                                 options |= VSZ;
456                                 break;
457                         }
458                         usage4 (_("VSZ must be an integer!"));
459                 case 'P':                                       /* PCPU */
460                         /* TODO: -P 1.5.5 is accepted */
461                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
462                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
463                                 options |= PCPU;
464                                 break;
465                         }
466                         usage4 (_("PCPU must be a float!"));
467                 case 'm':
468                         asprintf (&metric_name, "%s", optarg);
469                         if ( strcmp(optarg, "PROCS") == 0) {
470                                 metric = METRIC_PROCS;
471                                 break;
472                         } 
473                         else if ( strcmp(optarg, "VSZ") == 0) {
474                                 metric = METRIC_VSZ;
475                                 break;
476                         } 
477                         else if ( strcmp(optarg, "RSS") == 0 ) {
478                                 metric = METRIC_RSS;
479                                 break;
480                         }
481                         else if ( strcmp(optarg, "CPU") == 0 ) {
482                                 metric = METRIC_CPU;
483                                 break;
484                         }
485                         else if ( strcmp(optarg, "ELAPSED") == 0) {
486                                 metric = METRIC_ELAPSED;
487                                 break;
488                         }
489                                 
490                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
491                 case 'v':                                                                       /* command */
492                         verbose++;
493                         break;
494                 case CHAR_MAX+2:
495                         input_filename = optarg;
496                         break;
497                 }
498         }
500         c = optind;
501         if ((! warning_range) && argv[c])
502                 warning_range = argv[c++];
503         if ((! critical_range) && argv[c])
504                 critical_range = argv[c++];
505         if (statopts == NULL && argv[c]) {
506                 asprintf (&statopts, "%s", argv[c++]);
507                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
508                 options |= STAT;
509         }
511         /* this will abort in case of invalid ranges */
512         set_thresholds (&procs_thresholds, warning_range, critical_range);
514         return validate_arguments ();
519 int
520 validate_arguments ()
522         if (options == 0)
523                 options = ALL;
525         if (statopts==NULL)
526                 statopts = strdup("");
528         if (prog==NULL)
529                 prog = strdup("");
531         if (args==NULL)
532                 args = strdup("");
534         if (fmt==NULL)
535                 fmt = strdup("");
537         if (fails==NULL)
538                 fails = strdup("");
540         return options;
544 /* convert the elapsed time to seconds */
545 int
546 convert_to_seconds(char *etime) {
548         char *ptr;
549         int total;
551         int hyphcnt;
552         int coloncnt;
553         int days;
554         int hours;
555         int minutes;
556         int seconds;
558         hyphcnt = 0;
559         coloncnt = 0;
560         days = 0;
561         hours = 0;
562         minutes = 0;
563         seconds = 0;
565         for (ptr = etime; *ptr != '\0'; ptr++) {
566         
567                 if (*ptr == '-') {
568                         hyphcnt++;
569                         continue;
570                 }
571                 if (*ptr == ':') {
572                         coloncnt++;
573                         continue;
574                 }
575         }
577         if (hyphcnt > 0) {
578                 sscanf(etime, "%d-%d:%d:%d",
579                                 &days, &hours, &minutes, &seconds);
580                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
581                  * elapsed times for some reason */
582                 if (days == 49710) {
583                         return 0;
584                 }
585         } else {
586                 if (coloncnt == 2) {
587                         sscanf(etime, "%d:%d:%d",
588                                 &hours, &minutes, &seconds);
589                 } else if (coloncnt == 1) {
590                         sscanf(etime, "%d:%d",
591                                 &minutes, &seconds);
592                 }
593         }
595         total = (days * 86400) +
596                 (hours * 3600) +
597                 (minutes * 60) +
598                 seconds;
600         if (verbose >= 3 && metric == METRIC_ELAPSED) {
601                         printf("seconds: %d\n", total);
602         }
603         return total;
607 void
608 print_help (void)
610         print_revision (progname, NP_VERSION);
612         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
613         printf (COPYRIGHT, copyright, email);
615         printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
616   printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
617   printf ("%s\n", _("of processes.  Search filters can be applied to limit the processes to check."));
619   printf ("\n\n");
621         print_usage ();
623   printf (UT_HELP_VRSN);
624   printf (UT_EXTRA_OPTS);
625   printf (" %s\n", "-w, --warning=RANGE");
626   printf ("   %s\n", _("Generate warning state if metric is outside this range"));
627   printf (" %s\n", "-c, --critical=RANGE");
628   printf ("   %s\n", _("Generate critical state if metric is outside this range"));
629   printf (" %s\n", "-m, --metric=TYPE");
630   printf ("  %s\n", _("Check thresholds against metric. Valid types:"));
631   printf ("  %s\n", _("PROCS   - number of processes (default)"));
632   printf ("  %s\n", _("VSZ     - virtual memory size"));
633   printf ("  %s\n", _("RSS     - resident set memory size"));
634   printf ("  %s\n", _("CPU     - percentage CPU"));
635 /* only linux etime is support currently */
636 #if defined( __linux__ )
637         printf ("  %s\n", _("ELAPSED - time elapsed in seconds"));
638 #endif /* defined(__linux__) */
639         printf (UT_TIMEOUT, DEFAULT_SOCKET_TIMEOUT);
641         printf (" %s\n", "-v, --verbose");
642   printf ("    %s\n", _("Extra information. Up to 3 verbosity levels"));
644   printf ("\n");
645         printf ("%s\n", "Filters:");
646   printf (" %s\n", "-s, --state=STATUSFLAGS");
647   printf ("   %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
648   printf ("   %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
649   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
650   printf (" %s\n", "-p, --ppid=PPID");
651   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
652   printf (" %s\n", "-z, --vsz=VSZ");
653   printf ("   %s\n", _("Only scan for processes with VSZ higher than indicated."));
654   printf (" %s\n", "-r, --rss=RSS");
655   printf ("   %s\n", _("Only scan for processes with RSS higher than indicated."));
656         printf (" %s\n", "-P, --pcpu=PCPU");
657   printf ("   %s\n", _("Only scan for processes with PCPU higher than indicated."));
658   printf (" %s\n", "-u, --user=USER");
659   printf ("   %s\n", _("Only scan for processes with user name or ID indicated."));
660   printf (" %s\n", "-a, --argument-array=STRING");
661   printf ("   %s\n", _("Only scan for processes with args that contain STRING."));
662   printf (" %s\n", "--ereg-argument-array=STRING");
663   printf ("   %s\n", _("Only scan for processes with args that contain the regex STRING."));
664   printf (" %s\n", "-C, --command=COMMAND");
665   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
667         printf(_("\n\
668 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
669 specified 'max:min', a warning status will be generated if the\n\
670 count is inside the specified range\n\n"));
672         printf(_("\
673 This plugin checks the number of currently running processes and\n\
674 generates WARNING or CRITICAL states if the process count is outside\n\
675 the specified threshold ranges. The process count can be filtered by\n\
676 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
677 be the total number of running processes\n\n"));
679         printf ("%s\n", _("Examples:"));
680   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
681   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
682   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
683   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
684   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
685   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
686   printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
687   printf ("  %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
688   printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
689   printf ("  %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
691         printf (UT_SUPPORT);
694 void
695 print_usage (void)
697   printf ("%s\n", _("Usage:"));
698         printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
699   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
700   printf (" [-C command] [-t timeout] [-v]\n");