Code

Typo fixes (Jan Wagner - SF 1878971)
[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 check_thresholds (int);
49 int convert_to_seconds (char *); 
50 void print_help (void);
51 void print_usage (void);
53 int wmax = -1;
54 int cmax = -1;
55 int wmin = -1;
56 int cmin = -1;
58 int options = 0; /* bitmask of filter criteria to test against */
59 #define ALL 1
60 #define STAT 2
61 #define PPID 4
62 #define USER 8
63 #define PROG 16
64 #define ARGS 32
65 #define VSZ  64
66 #define RSS  128
67 #define PCPU 256
68 #define ELAPSED 512
69 #define EREG_ARGS 1024
70 /* Different metrics */
71 char *metric_name;
72 enum metric {
73         METRIC_PROCS,
74         METRIC_VSZ,
75         METRIC_RSS,
76         METRIC_CPU,
77         METRIC_ELAPSED
78 };
79 enum metric metric = METRIC_PROCS;
81 int verbose = 0;
82 int uid;
83 pid_t ppid;
84 int vsz;
85 int rss;
86 float pcpu;
87 char *statopts;
88 char *prog;
89 char *args;
90 char *input_filename = NULL;
91 regex_t re_args;
92 char *fmt;
93 char *fails;
94 char tmp[MAX_INPUT_BUFFER];
96 FILE *ps_input = NULL;
99 int
100 main (int argc, char **argv)
102         char *input_buffer;
103         char *input_line;
104         char *procprog;
106         pid_t mypid = 0;
107         int procuid = 0;
108         pid_t procpid = 0;
109         pid_t procppid = 0;
110         int procvsz = 0;
111         int procrss = 0;
112         int procseconds = 0;
113         float procpcpu = 0;
114         char procstat[8];
115         char procetime[MAX_INPUT_BUFFER] = { '\0' };
116         char *procargs;
118         const char *zombie = "Z";
120         int resultsum = 0; /* bitmask of the filter criteria met by a process */
121         int found = 0; /* counter for number of lines returned in `ps` output */
122         int procs = 0; /* counter for number of processes meeting filter criteria */
123         int pos; /* number of spaces before 'args' in `ps` output */
124         int cols; /* number of columns in ps output */
125         int expected_cols = PS_COLS - 1;
126         int warn = 0; /* number of processes in warn state */
127         int crit = 0; /* number of processes in crit state */
128         int i = 0, j = 0;
129         int result = STATE_UNKNOWN;
130         output chld_out, chld_err;
132         setlocale (LC_ALL, "");
133         bindtextdomain (PACKAGE, LOCALEDIR);
134         textdomain (PACKAGE);
135         setlocale(LC_NUMERIC, "POSIX");
137         input_buffer = malloc (MAX_INPUT_BUFFER);
138         procprog = malloc (MAX_INPUT_BUFFER);
140         asprintf (&metric_name, "PROCS");
141         metric = METRIC_PROCS;
143         /* Parse extra opts if any */
144         argv=np_extra_opts (&argc, argv, progname);
146         if (process_arguments (argc, argv) == ERROR)
147                 usage4 (_("Could not parse arguments"));
149         /* get our pid */
150         mypid = getpid();
152         /* Set signal handling and alarm timeout */
153         if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
154                 die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
155         }
156         (void) alarm ((unsigned) timeout_interval);
158         if (verbose >= 2)
159                 printf (_("CMD: %s\n"), PS_COMMAND);
161         if (input_filename == NULL) {
162                 result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
163                 if (chld_err.lines > 0) {
164                         printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
165                         exit(STATE_WARNING);
166                 }
167         } else {
168                 result = cmd_file_read( input_filename, &chld_out, 0);
169         }
171         /* flush first line: j starts at 1 */
172         for (j = 1; j < chld_out.lines; j++) {
173                 input_line = chld_out.line[j];
175                 if (verbose >= 3)
176                         printf ("%s", input_line);
178                 strcpy (procprog, "");
179                 asprintf (&procargs, "%s", "");
181                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
183                 /* Zombie processes do not give a procprog command */
184                 if ( cols < expected_cols && strstr(procstat, zombie) ) {
185                         cols = expected_cols;
186                 }
187                 if ( cols >= expected_cols ) {
188                         resultsum = 0;
189                         asprintf (&procargs, "%s", input_line + pos);
190                         strip (procargs);
192                         /* Some ps return full pathname for command. This removes path */
193                         strcpy(procprog, base_name(procprog));
195                         /* we need to convert the elapsed time to seconds */
196                         procseconds = convert_to_seconds(procetime);
198                         if (verbose >= 3)
199                                 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
200                                         procs, procuid, procvsz, procrss,
201                                         procpid, procppid, procpcpu, procstat, 
202                                         procetime, procprog, procargs);
204                         /* Ignore self */
205                         if (mypid == procpid) continue;
207                         if ((options & STAT) && (strstr (statopts, procstat)))
208                                 resultsum |= STAT;
209                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
210                                 resultsum |= ARGS;
211                         if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
212                                 resultsum |= EREG_ARGS;
213                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
214                                 resultsum |= PROG;
215                         if ((options & PPID) && (procppid == ppid))
216                                 resultsum |= PPID;
217                         if ((options & USER) && (procuid == uid))
218                                 resultsum |= USER;
219                         if ((options & VSZ)  && (procvsz >= vsz))
220                                 resultsum |= VSZ;
221                         if ((options & RSS)  && (procrss >= rss))
222                                 resultsum |= RSS;
223                         if ((options & PCPU)  && (procpcpu >= pcpu))
224                                 resultsum |= PCPU;
226                         found++;
228                         /* Next line if filters not matched */
229                         if (!(options == resultsum || options == ALL))
230                                 continue;
232                         procs++;
233                         if (verbose >= 2) {
234                                 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
235                                         procuid, procvsz, procrss,
236                                         procpid, procppid, procpcpu, procstat, 
237                                         procetime, procprog, procargs);
238                         }
240                         if (metric == METRIC_VSZ)
241                                 i = check_thresholds (procvsz);
242                         else if (metric == METRIC_RSS)
243                                 i = check_thresholds (procrss);
244                         /* TODO? float thresholds for --metric=CPU */
245                         else if (metric == METRIC_CPU)
246                                 i = check_thresholds ((int)procpcpu); 
247                         else if (metric == METRIC_ELAPSED)
248                                 i = check_thresholds (procseconds);
250                         if (metric != METRIC_PROCS) {
251                                 if (i == STATE_WARNING) {
252                                         warn++;
253                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
254                                         result = max_state (result, i);
255                                 }
256                                 if (i == STATE_CRITICAL) {
257                                         crit++;
258                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
259                                         result = max_state (result, i);
260                                 }
261                         }
262                 } 
263                 /* This should not happen */
264                 else if (verbose) {
265                         printf(_("Not parseable: %s"), input_buffer);
266                 }
267         }
269         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
270                 printf (_("Unable to read output\n"));
271                 return STATE_UNKNOWN;
272         }
274         if ( result == STATE_UNKNOWN ) 
275                 result = STATE_OK;
277         /* Needed if procs found, but none match filter */
278         if ( metric == METRIC_PROCS ) {
279                 result = max_state (result, check_thresholds (procs) );
280         }
282         if ( result == STATE_OK ) {
283                 printf ("%s %s: ", metric_name, _("OK"));
284         } else if (result == STATE_WARNING) {
285                 printf ("%s %s: ", metric_name, _("WARNING"));
286                 if ( metric != METRIC_PROCS ) {
287                         printf (_("%d warn out of "), warn);
288                 }
289         } else if (result == STATE_CRITICAL) {
290                 printf ("%s %s: ", metric_name, _("CRITICAL"));
291                 if (metric != METRIC_PROCS) {
292                         printf (_("%d crit, %d warn out of "), crit, warn);
293                 }
294         } 
295         printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
296         
297         if (strcmp(fmt,"") != 0) {
298                 printf (_(" with %s"), fmt);
299         }
301         if ( verbose >= 1 && strcmp(fails,"") )
302                 printf (" [%s]", fails);
304         printf ("\n");
305         return result;
310 /* process command-line arguments */
311 int
312 process_arguments (int argc, char **argv)
314         int c = 1;
315         char *user;
316         struct passwd *pw;
317         int option = 0;
318         int err;
319         int cflags = REG_NOSUB | REG_EXTENDED;
320         char errbuf[MAX_INPUT_BUFFER];
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                         if (is_integer (optarg))
370                                 cmax = atoi (optarg);
371                         else if (sscanf (optarg, ":%d", &cmax) == 1)
372                                 break;
373                         else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
374                                 break;
375                         else if (sscanf (optarg, "%d:", &cmin) == 1)
376                                 break;
377                         else
378                                 usage4 (_("Critical Process Count must be an integer!"));
379                         break;                                                   
380                 case 'w':                                                                       /* warning threshold */
381                         if (is_integer (optarg))
382                                 wmax = atoi (optarg);
383                         else if (sscanf (optarg, ":%d", &wmax) == 1)
384                                 break;
385                         else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
386                                 break;
387                         else if (sscanf (optarg, "%d:", &wmin) == 1)
388                                 break;
389                         else
390                                 usage4 (_("Warning Process Count must be an integer!"));
391                         break;
392                 case 'p':                                                                       /* process id */
393                         if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
394                                 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
395                                 options |= PPID;
396                                 break;
397                         }
398                         usage4 (_("Parent Process ID must be an integer!"));
399                 case 's':                                                                       /* status */
400                         if (statopts)
401                                 break;
402                         else
403                                 statopts = optarg;
404                         asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
405                         options |= STAT;
406                         break;
407                 case 'u':                                                                       /* user or user id */
408                         if (is_integer (optarg)) {
409                                 uid = atoi (optarg);
410                                 pw = getpwuid ((uid_t) uid);
411                                 /*  check to be sure user exists */
412                                 if (pw == NULL)
413                                         usage2 (_("UID was not found"), optarg);
414                         }
415                         else {
416                                 pw = getpwnam (optarg);
417                                 /*  check to be sure user exists */
418                                 if (pw == NULL)
419                                         usage2 (_("User name was not found"), optarg);
420                                 /*  then get uid */
421                                 uid = pw->pw_uid;
422                         }
423                         user = pw->pw_name;
424                         asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
425                                   uid, user);
426                         options |= USER;
427                         break;
428                 case 'C':                                                                       /* command */
429                         /* TODO: allow this to be passed in with --metric */
430                         if (prog)
431                                 break;
432                         else
433                                 prog = optarg;
434                         asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
435                                   prog);
436                         options |= PROG;
437                         break;
438                 case 'a':                                                                       /* args (full path name with args) */
439                         /* TODO: allow this to be passed in with --metric */
440                         if (args)
441                                 break;
442                         else
443                                 args = optarg;
444                         asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
445                         options |= ARGS;
446                         break;
447                 case CHAR_MAX+1:
448                         err = regcomp(&re_args, optarg, cflags);
449                         if (err != 0) {
450                                 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
451                                 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
452                         }
453                         asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
454                         options |= EREG_ARGS;
455                         break;
456                 case 'r':                                       /* RSS */
457                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
458                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
459                                 options |= RSS;
460                                 break;
461                         }
462                         usage4 (_("RSS must be an integer!"));
463                 case 'z':                                       /* VSZ */
464                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
465                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
466                                 options |= VSZ;
467                                 break;
468                         }
469                         usage4 (_("VSZ must be an integer!"));
470                 case 'P':                                       /* PCPU */
471                         /* TODO: -P 1.5.5 is accepted */
472                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
473                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
474                                 options |= PCPU;
475                                 break;
476                         }
477                         usage4 (_("PCPU must be a float!"));
478                 case 'm':
479                         asprintf (&metric_name, "%s", optarg);
480                         if ( strcmp(optarg, "PROCS") == 0) {
481                                 metric = METRIC_PROCS;
482                                 break;
483                         } 
484                         else if ( strcmp(optarg, "VSZ") == 0) {
485                                 metric = METRIC_VSZ;
486                                 break;
487                         } 
488                         else if ( strcmp(optarg, "RSS") == 0 ) {
489                                 metric = METRIC_RSS;
490                                 break;
491                         }
492                         else if ( strcmp(optarg, "CPU") == 0 ) {
493                                 metric = METRIC_CPU;
494                                 break;
495                         }
496                         else if ( strcmp(optarg, "ELAPSED") == 0) {
497                                 metric = METRIC_ELAPSED;
498                                 break;
499                         }
500                                 
501                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
502                 case 'v':                                                                       /* command */
503                         verbose++;
504                         break;
505                 case CHAR_MAX+2:
506                         input_filename = optarg;
507                         break;
508                 }
509         }
511         c = optind;
512         if (wmax == -1 && argv[c])
513                 wmax = atoi (argv[c++]);
514         if (cmax == -1 && argv[c])
515                 cmax = atoi (argv[c++]);
516         if (statopts == NULL && argv[c]) {
517                 asprintf (&statopts, "%s", argv[c++]);
518                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
519                 options |= STAT;
520         }
522         return validate_arguments ();
527 int
528 validate_arguments ()
531         if (wmax >= 0 && wmin == -1)
532                 wmin = 0;
533         if (cmax >= 0 && cmin == -1)
534                 cmin = 0;
535         if (wmax >= wmin && cmax >= cmin) {     /* standard ranges */
536                 if (wmax > cmax && cmax != -1) {
537                         printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
538                         return ERROR;
539                 }
540                 if (cmin > wmin && wmin != -1) {
541                         printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
542                         return ERROR;
543                 }
544         }
546 /*      if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
547 /*              printf ("At least one threshold must be set\n"); */
548 /*              return ERROR; */
549 /*      } */
551         if (options == 0)
552                 options = ALL;
554         if (statopts==NULL)
555                 statopts = strdup("");
557         if (prog==NULL)
558                 prog = strdup("");
560         if (args==NULL)
561                 args = strdup("");
563         if (fmt==NULL)
564                 fmt = strdup("");
566         if (fails==NULL)
567                 fails = strdup("");
569         return options;
574 /* Check thresholds against value */
575 int
576 check_thresholds (int value)
578         if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
579                 return OK;
580         }
581         else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
582                 if (value > cmax && value < cmin)
583                         return STATE_CRITICAL;
584         }
585         else if (cmax >= 0 && value > cmax) {
586                 return STATE_CRITICAL;
587         }
588         else if (cmin >= 0 && value < cmin) {
589                 return STATE_CRITICAL;
590         }
592         if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
593                 if (value > wmax && value < wmin) {
594                         return STATE_WARNING;
595                 }
596         }
597         else if (wmax >= 0 && value > wmax) {
598                 return STATE_WARNING;
599         }
600         else if (wmin >= 0 && value < wmin) {
601                 return STATE_WARNING;
602         }
603         return STATE_OK;
607 /* convert the elapsed time to seconds */
608 int
609 convert_to_seconds(char *etime) {
611         char *ptr;
612         int total;
614         int hyphcnt;
615         int coloncnt;
616         int days;
617         int hours;
618         int minutes;
619         int seconds;
621         hyphcnt = 0;
622         coloncnt = 0;
623         days = 0;
624         hours = 0;
625         minutes = 0;
626         seconds = 0;
628         for (ptr = etime; *ptr != '\0'; ptr++) {
629         
630                 if (*ptr == '-') {
631                         hyphcnt++;
632                         continue;
633                 }
634                 if (*ptr == ':') {
635                         coloncnt++;
636                         continue;
637                 }
638         }
640         if (hyphcnt > 0) {
641                 sscanf(etime, "%d-%d:%d:%d",
642                                 &days, &hours, &minutes, &seconds);
643                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
644                  * elapsed times for some reason */
645                 if (days == 49710) {
646                         return 0;
647                 }
648         } else {
649                 if (coloncnt == 2) {
650                         sscanf(etime, "%d:%d:%d",
651                                 &hours, &minutes, &seconds);
652                 } else if (coloncnt == 1) {
653                         sscanf(etime, "%d:%d",
654                                 &minutes, &seconds);
655                 }
656         }
658         total = (days * 86400) +
659                 (hours * 3600) +
660                 (minutes * 60) +
661                 seconds;
663         if (verbose >= 3 && metric == METRIC_ELAPSED) {
664                         printf("seconds: %d\n", total);
665         }
666         return total;
670 void
671 print_help (void)
673         print_revision (progname, NP_VERSION);
675         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
676         printf (COPYRIGHT, copyright, email);
678         printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
679   printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
680   printf ("%s\n", _("of processes.  Search filters can be applied to limit the processes to check."));
682   printf ("\n\n");
684         print_usage ();
686   printf (_(UT_HELP_VRSN));
687   printf (_(UT_EXTRA_OPTS));
688   printf (" %s\n", "-w, --warning=RANGE");
689   printf ("   %s\n", _("Generate warning state if metric is outside this range"));
690   printf (" %s\n", "-c, --critical=RANGE");
691   printf ("   %s\n", _("Generate critical state if metric is outside this range"));
692   printf (" %s\n", "-m, --metric=TYPE");
693   printf ("  %s\n", _("Check thresholds against metric. Valid types:"));
694   printf ("  %s\n", _("PROCS   - number of processes (default)"));
695   printf ("  %s\n", _("VSZ     - virtual memory size"));
696   printf ("  %s\n", _("RSS     - resident set memory size"));
697   printf ("  %s\n", _("CPU     - percentage CPU"));
698 /* only linux etime is support currently */
699 #if defined( __linux__ )
700         printf ("  %s\n", _("ELAPSED - time elapsed in seconds"));
701 #endif /* defined(__linux__) */
702         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
704         printf (" %s\n", "-v, --verbose");
705   printf ("    %s\n", _("Extra information. Up to 3 verbosity levels"));
707   printf ("\n");
708         printf ("%s\n", "Filters:");
709   printf (" %s\n", "-s, --state=STATUSFLAGS");
710   printf ("   %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
711   printf ("   %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
712   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
713   printf (" %s\n", "-p, --ppid=PPID");
714   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
715   printf (" %s\n", "-z, --vsz=VSZ");
716   printf ("   %s\n", _("Only scan for processes with VSZ higher than indicated."));
717   printf (" %s\n", "-r, --rss=RSS");
718   printf ("   %s\n", _("Only scan for processes with RSS higher than indicated."));
719         printf (" %s\n", "-P, --pcpu=PCPU");
720   printf ("   %s\n", _("Only scan for processes with PCPU higher than indicated."));
721   printf (" %s\n", "-u, --user=USER");
722   printf ("   %s\n", _("Only scan for processes with user name or ID indicated."));
723   printf (" %s\n", "-a, --argument-array=STRING");
724   printf ("   %s\n", _("Only scan for processes with args that contain STRING."));
725   printf (" %s\n", "--ereg-argument-array=STRING");
726   printf ("   %s\n", _("Only scan for processes with args that contain the regex STRING."));
727   printf (" %s\n", "-C, --command=COMMAND");
728   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
730         printf(_("\n\
731 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
732 specified 'max:min', a warning status will be generated if the\n\
733 count is inside the specified range\n\n"));
735         printf(_("\
736 This plugin checks the number of currently running processes and\n\
737 generates WARNING or CRITICAL states if the process count is outside\n\
738 the specified threshold ranges. The process count can be filtered by\n\
739 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
740 be the total number of running processes\n\n"));
742 #ifdef NP_EXTRA_OPTS
743   printf ("%s\n", _("Notes:"));
744   printf (_(UT_EXTRA_OPTS_NOTES));
745   printf ("\n");
746 #endif
748         printf ("%s\n", _("Examples:"));
749   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
750   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
751   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
752   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
753   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
754   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
755   printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
756   printf ("  %s\n\n", _("Alert if VSZ of any processes over 50K or 100K"));
757   printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
758   printf ("  %s\n", _("Alert if CPU of any processes over 10%% or 20%%"));
760         printf (_(UT_SUPPORT));
763 void
764 print_usage (void)
766   printf (_("Usage: "));
767         printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
768   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
769   printf (" [-C command] [-t timeout] [-v]\n");