Code

Updated check_procs with a hidden --input-file option.
[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 * Last Modified: $Date$
9
10 * Description:
11
12 * This file contains the check_procs plugin
13
14 * Checks all processes and generates WARNING or CRITICAL states if the
15 * specified metric is outside the required threshold ranges. The metric
16 * defaults to number of processes.  Search filters can be applied to limit
17 * the processes to check.
18
19
20 * This program is free software: you can redistribute it and/or modify
21 * it under the terms of the GNU General Public License as published by
22 * the Free Software Foundation, either version 3 of the License, or
23 * (at your option) any later version.
24
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
28 * GNU General Public License for more details.
29
30 * You should have received a copy of the GNU General Public License
31 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
32
33 * $Id$
34
35 *****************************************************************************/
37 const char *progname = "check_procs";
38 const char *program_name = "check_procs";  /* Required for coreutils libs */
39 const char *revision = "$Revision$";
40 const char *copyright = "2000-2008";
41 const char *email = "nagiosplug-devel@lists.sourceforge.net";
43 #include "common.h"
44 #include "popen.h"
45 #include "utils.h"
46 #include "regex.h"
48 #include <pwd.h>
50 int process_arguments (int, char **);
51 int validate_arguments (void);
52 int check_thresholds (int);
53 int convert_to_seconds (char *); 
54 void print_help (void);
55 void print_usage (void);
57 int wmax = -1;
58 int cmax = -1;
59 int wmin = -1;
60 int cmin = -1;
62 int options = 0; /* bitmask of filter criteria to test against */
63 #define ALL 1
64 #define STAT 2
65 #define PPID 4
66 #define USER 8
67 #define PROG 16
68 #define ARGS 32
69 #define VSZ  64
70 #define RSS  128
71 #define PCPU 256
72 #define ELAPSED 512
73 #define EREG_ARGS 1024
74 /* Different metrics */
75 char *metric_name;
76 enum metric {
77         METRIC_PROCS,
78         METRIC_VSZ,
79         METRIC_RSS,
80         METRIC_CPU,
81         METRIC_ELAPSED
82 };
83 enum metric metric = METRIC_PROCS;
85 int verbose = 0;
86 int uid;
87 pid_t ppid;
88 int vsz;
89 int rss;
90 float pcpu;
91 char *statopts;
92 char *prog;
93 char *args;
94 char *input_filename = NULL;
95 regex_t re_args;
96 char *fmt;
97 char *fails;
98 char tmp[MAX_INPUT_BUFFER];
100 FILE *ps_input = NULL;
103 int
104 main (int argc, char **argv)
106         char *input_buffer;
107         char *input_line;
108         char *procprog;
110         pid_t mypid = 0;
111         int procuid = 0;
112         pid_t procpid = 0;
113         pid_t procppid = 0;
114         int procvsz = 0;
115         int procrss = 0;
116         int procseconds = 0;
117         float procpcpu = 0;
118         char procstat[8];
119         char procetime[MAX_INPUT_BUFFER] = { '\0' };
120         char *procargs;
122         const char *zombie = "Z";
124         int resultsum = 0; /* bitmask of the filter criteria met by a process */
125         int found = 0; /* counter for number of lines returned in `ps` output */
126         int procs = 0; /* counter for number of processes meeting filter criteria */
127         int pos; /* number of spaces before 'args' in `ps` output */
128         int cols; /* number of columns in ps output */
129         int expected_cols = PS_COLS - 1;
130         int warn = 0; /* number of processes in warn state */
131         int crit = 0; /* number of processes in crit state */
132         int i = 0;
133         int result = STATE_UNKNOWN;
135         setlocale (LC_ALL, "");
136         bindtextdomain (PACKAGE, LOCALEDIR);
137         textdomain (PACKAGE);
138         setlocale(LC_NUMERIC, "POSIX");
140         input_buffer = malloc (MAX_INPUT_BUFFER);
141         procprog = malloc (MAX_INPUT_BUFFER);
143         asprintf (&metric_name, "PROCS");
144         metric = METRIC_PROCS;
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, popen_timeout_alarm_handler) == SIG_ERR) {
154                 usage4 (_("Cannot catch SIGALRM"));
155         }
156         alarm (timeout_interval);
158         if (verbose >= 2)
159                 printf (_("CMD: %s\n"), PS_COMMAND);
161         if (input_filename == NULL) {
162                 ps_input = spopen (PS_COMMAND);
163                 if (ps_input == NULL) {
164                         printf (_("Could not open pipe: %s\n"), PS_COMMAND);
165                         return STATE_UNKNOWN;
166                 }
167                 child_stderr = fdopen (child_stderr_array[fileno (ps_input)], "r");
168                 if (child_stderr == NULL)
169                         printf (_("Could not open stderr for %s\n"), PS_COMMAND);
170         } else {
171                 ps_input = fopen(input_filename, "r");
172                 if (ps_input == NULL) {
173                         die( STATE_UNKNOWN, _("Error opening %s\n"), input_filename );
174                 }
175         }
177         /* flush first line */
178         fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
179         while ( input_buffer[strlen(input_buffer)-1] != '\n' )
180                 fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
182         while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input)) {
183                 asprintf (&input_line, "%s", input_buffer);
184                 while ( input_buffer[strlen(input_buffer)-1] != '\n' ) {
185                         fgets (input_buffer, MAX_INPUT_BUFFER - 1, ps_input);
186                         asprintf (&input_line, "%s%s", input_line, input_buffer);
187                 }
189                 if (verbose >= 3)
190                         printf ("%s", input_line);
192                 strcpy (procprog, "");
193                 asprintf (&procargs, "%s", "");
195                 cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
197                 /* Zombie processes do not give a procprog command */
198                 if ( cols < expected_cols && strstr(procstat, zombie) ) {
199                         cols = expected_cols;
200                 }
201                 if ( cols >= expected_cols ) {
202                         resultsum = 0;
203                         asprintf (&procargs, "%s", input_line + pos);
204                         strip (procargs);
206                         /* Some ps return full pathname for command. This removes path */
207                         strcpy(procprog, base_name(procprog));
209                         /* we need to convert the elapsed time to seconds */
210                         procseconds = convert_to_seconds(procetime);
212                         if (verbose >= 3)
213                                 printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
214                                         procs, procuid, procvsz, procrss,
215                                         procpid, procppid, procpcpu, procstat, 
216                                         procetime, procprog, procargs);
218                         /* Ignore self */
219                         if (mypid == procpid) continue;
221                         if ((options & STAT) && (strstr (statopts, procstat)))
222                                 resultsum |= STAT;
223                         if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
224                                 resultsum |= ARGS;
225                         if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
226                                 resultsum |= EREG_ARGS;
227                         if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
228                                 resultsum |= PROG;
229                         if ((options & PPID) && (procppid == ppid))
230                                 resultsum |= PPID;
231                         if ((options & USER) && (procuid == uid))
232                                 resultsum |= USER;
233                         if ((options & VSZ)  && (procvsz >= vsz))
234                                 resultsum |= VSZ;
235                         if ((options & RSS)  && (procrss >= rss))
236                                 resultsum |= RSS;
237                         if ((options & PCPU)  && (procpcpu >= pcpu))
238                                 resultsum |= PCPU;
240                         found++;
242                         /* Next line if filters not matched */
243                         if (!(options == resultsum || options == ALL))
244                                 continue;
246                         procs++;
247                         if (verbose >= 2) {
248                                 printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n", 
249                                         procuid, procvsz, procrss,
250                                         procpid, procppid, procpcpu, procstat, 
251                                         procetime, procprog, procargs);
252                         }
254                         if (metric == METRIC_VSZ)
255                                 i = check_thresholds (procvsz);
256                         else if (metric == METRIC_RSS)
257                                 i = check_thresholds (procrss);
258                         /* TODO? float thresholds for --metric=CPU */
259                         else if (metric == METRIC_CPU)
260                                 i = check_thresholds ((int)procpcpu); 
261                         else if (metric == METRIC_ELAPSED)
262                                 i = check_thresholds (procseconds);
264                         if (metric != METRIC_PROCS) {
265                                 if (i == STATE_WARNING) {
266                                         warn++;
267                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
268                                         result = max_state (result, i);
269                                 }
270                                 if (i == STATE_CRITICAL) {
271                                         crit++;
272                                         asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
273                                         result = max_state (result, i);
274                                 }
275                         }
276                 } 
277                 /* This should not happen */
278                 else if (verbose) {
279                         printf(_("Not parseable: %s"), input_buffer);
280                 }
281         }
283         /* If we get anything on STDERR, at least set warning */
284         if (input_filename == NULL) {
285                 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
286                         if (verbose)
287                                 printf ("STDERR: %s", input_buffer);
288                         result = max_state (result, STATE_WARNING);
289                         printf (_("System call sent warnings to stderr\n"));
290                 }
291         
292                 (void) fclose (child_stderr);
294                 /* close the pipe */
295                 if (spclose (ps_input)) {
296                         printf (_("System call returned nonzero status\n"));
297                         result = max_state (result, STATE_WARNING);
298                 }
299         }
301         if (found == 0) {                                                       /* no process lines parsed so return STATE_UNKNOWN */
302                 printf (_("Unable to read output\n"));
303                 return result;
304         }
306         if ( result == STATE_UNKNOWN ) 
307                 result = STATE_OK;
309         /* Needed if procs found, but none match filter */
310         if ( metric == METRIC_PROCS ) {
311                 result = max_state (result, check_thresholds (procs) );
312         }
314         if ( result == STATE_OK ) {
315                 printf ("%s %s: ", metric_name, _("OK"));
316         } else if (result == STATE_WARNING) {
317                 printf ("%s %s: ", metric_name, _("WARNING"));
318                 if ( metric != METRIC_PROCS ) {
319                         printf (_("%d warn out of "), warn);
320                 }
321         } else if (result == STATE_CRITICAL) {
322                 printf ("%s %s: ", metric_name, _("CRITICAL"));
323                 if (metric != METRIC_PROCS) {
324                         printf (_("%d crit, %d warn out of "), crit, warn);
325                 }
326         } 
327         printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
328         
329         if (strcmp(fmt,"") != 0) {
330                 printf (_(" with %s"), fmt);
331         }
333         if ( verbose >= 1 && strcmp(fails,"") )
334                 printf (" [%s]", fails);
336         printf ("\n");
337         return result;
342 /* process command-line arguments */
343 int
344 process_arguments (int argc, char **argv)
346         int c = 1;
347         char *user;
348         struct passwd *pw;
349         int option = 0;
350         int err;
351         int cflags = REG_NOSUB | REG_EXTENDED;
352         char errbuf[MAX_INPUT_BUFFER];
353         static struct option longopts[] = {
354                 {"warning", required_argument, 0, 'w'},
355                 {"critical", required_argument, 0, 'c'},
356                 {"metric", required_argument, 0, 'm'},
357                 {"timeout", required_argument, 0, 't'},
358                 {"status", required_argument, 0, 's'},
359                 {"ppid", required_argument, 0, 'p'},
360                 {"command", required_argument, 0, 'C'},
361                 {"vsz", required_argument, 0, 'z'},
362                 {"rss", required_argument, 0, 'r'},
363                 {"pcpu", required_argument, 0, 'P'},
364                 {"elapsed", required_argument, 0, 'e'},
365                 {"argument-array", required_argument, 0, 'a'},
366                 {"help", no_argument, 0, 'h'},
367                 {"version", no_argument, 0, 'V'},
368                 {"verbose", no_argument, 0, 'v'},
369                 {"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
370                 {"input-file", required_argument, 0, CHAR_MAX+2},
371                 {0, 0, 0, 0}
372         };
374         for (c = 1; c < argc; c++)
375                 if (strcmp ("-to", argv[c]) == 0)
376                         strcpy (argv[c], "-t");
378         while (1) {
379                 c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:", 
380                         longopts, &option);
382                 if (c == -1 || c == EOF)
383                         break;
385                 switch (c) {
386                 case '?':                                                                       /* help */
387                         usage5 ();
388                 case 'h':                                                                       /* help */
389                         print_help ();
390                         exit (STATE_OK);
391                 case 'V':                                                                       /* version */
392                         print_revision (progname, revision);
393                         exit (STATE_OK);
394                 case 't':                                                                       /* timeout period */
395                         if (!is_integer (optarg))
396                                 usage2 (_("Timeout interval must be a positive integer"), optarg);
397                         else
398                                 timeout_interval = atoi (optarg);
399                         break;
400                 case 'c':                                                                       /* critical threshold */
401                         if (is_integer (optarg))
402                                 cmax = atoi (optarg);
403                         else if (sscanf (optarg, ":%d", &cmax) == 1)
404                                 break;
405                         else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2)
406                                 break;
407                         else if (sscanf (optarg, "%d:", &cmin) == 1)
408                                 break;
409                         else
410                                 usage4 (_("Critical Process Count must be an integer!"));
411                         break;                                                   
412                 case 'w':                                                                       /* warning threshold */
413                         if (is_integer (optarg))
414                                 wmax = atoi (optarg);
415                         else if (sscanf (optarg, ":%d", &wmax) == 1)
416                                 break;
417                         else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2)
418                                 break;
419                         else if (sscanf (optarg, "%d:", &wmin) == 1)
420                                 break;
421                         else
422                                 usage4 (_("Warning Process Count must be an integer!"));
423                         break;
424                 case 'p':                                                                       /* process id */
425                         if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
426                                 asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
427                                 options |= PPID;
428                                 break;
429                         }
430                         usage4 (_("Parent Process ID must be an integer!"));
431                 case 's':                                                                       /* status */
432                         if (statopts)
433                                 break;
434                         else
435                                 statopts = optarg;
436                         asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
437                         options |= STAT;
438                         break;
439                 case 'u':                                                                       /* user or user id */
440                         if (is_integer (optarg)) {
441                                 uid = atoi (optarg);
442                                 pw = getpwuid ((uid_t) uid);
443                                 /*  check to be sure user exists */
444                                 if (pw == NULL)
445                                         usage2 (_("UID was not found"), optarg);
446                         }
447                         else {
448                                 pw = getpwnam (optarg);
449                                 /*  check to be sure user exists */
450                                 if (pw == NULL)
451                                         usage2 (_("User name was not found"), optarg);
452                                 /*  then get uid */
453                                 uid = pw->pw_uid;
454                         }
455                         user = pw->pw_name;
456                         asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
457                                   uid, user);
458                         options |= USER;
459                         break;
460                 case 'C':                                                                       /* command */
461                         /* TODO: allow this to be passed in with --metric */
462                         if (prog)
463                                 break;
464                         else
465                                 prog = optarg;
466                         asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
467                                   prog);
468                         options |= PROG;
469                         break;
470                 case 'a':                                                                       /* args (full path name with args) */
471                         /* TODO: allow this to be passed in with --metric */
472                         if (args)
473                                 break;
474                         else
475                                 args = optarg;
476                         asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
477                         options |= ARGS;
478                         break;
479                 case CHAR_MAX+1:
480                         err = regcomp(&re_args, optarg, cflags);
481                         if (err != 0) {
482                                 regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
483                                 die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
484                         }
485                         asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
486                         options |= EREG_ARGS;
487                         break;
488                 case 'r':                                       /* RSS */
489                         if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
490                                 asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
491                                 options |= RSS;
492                                 break;
493                         }
494                         usage4 (_("RSS must be an integer!"));
495                 case 'z':                                       /* VSZ */
496                         if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
497                                 asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
498                                 options |= VSZ;
499                                 break;
500                         }
501                         usage4 (_("VSZ must be an integer!"));
502                 case 'P':                                       /* PCPU */
503                         /* TODO: -P 1.5.5 is accepted */
504                         if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
505                                 asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
506                                 options |= PCPU;
507                                 break;
508                         }
509                         usage4 (_("PCPU must be a float!"));
510                 case 'm':
511                         asprintf (&metric_name, "%s", optarg);
512                         if ( strcmp(optarg, "PROCS") == 0) {
513                                 metric = METRIC_PROCS;
514                                 break;
515                         } 
516                         else if ( strcmp(optarg, "VSZ") == 0) {
517                                 metric = METRIC_VSZ;
518                                 break;
519                         } 
520                         else if ( strcmp(optarg, "RSS") == 0 ) {
521                                 metric = METRIC_RSS;
522                                 break;
523                         }
524                         else if ( strcmp(optarg, "CPU") == 0 ) {
525                                 metric = METRIC_CPU;
526                                 break;
527                         }
528                         else if ( strcmp(optarg, "ELAPSED") == 0) {
529                                 metric = METRIC_ELAPSED;
530                                 break;
531                         }
532                                 
533                         usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
534                 case 'v':                                                                       /* command */
535                         verbose++;
536                         break;
537                 case CHAR_MAX+2:
538                         input_filename = optarg;
539                         break;
540                 }
541         }
543         c = optind;
544         if (wmax == -1 && argv[c])
545                 wmax = atoi (argv[c++]);
546         if (cmax == -1 && argv[c])
547                 cmax = atoi (argv[c++]);
548         if (statopts == NULL && argv[c]) {
549                 asprintf (&statopts, "%s", argv[c++]);
550                 asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
551                 options |= STAT;
552         }
554         return validate_arguments ();
559 int
560 validate_arguments ()
563         if (wmax >= 0 && wmin == -1)
564                 wmin = 0;
565         if (cmax >= 0 && cmin == -1)
566                 cmin = 0;
567         if (wmax >= wmin && cmax >= cmin) {     /* standard ranges */
568                 if (wmax > cmax && cmax != -1) {
569                         printf (_("wmax (%d) cannot be greater than cmax (%d)\n"), wmax, cmax);
570                         return ERROR;
571                 }
572                 if (cmin > wmin && wmin != -1) {
573                         printf (_("wmin (%d) cannot be less than cmin (%d)\n"), wmin, cmin);
574                         return ERROR;
575                 }
576         }
578 /*      if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) { */
579 /*              printf ("At least one threshold must be set\n"); */
580 /*              return ERROR; */
581 /*      } */
583         if (options == 0)
584                 options = ALL;
586         if (statopts==NULL)
587                 statopts = strdup("");
589         if (prog==NULL)
590                 prog = strdup("");
592         if (args==NULL)
593                 args = strdup("");
595         if (fmt==NULL)
596                 fmt = strdup("");
598         if (fails==NULL)
599                 fails = strdup("");
601         return options;
606 /* Check thresholds against value */
607 int
608 check_thresholds (int value)
610         if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
611                 return OK;
612         }
613         else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
614                 if (value > cmax && value < cmin)
615                         return STATE_CRITICAL;
616         }
617         else if (cmax >= 0 && value > cmax) {
618                 return STATE_CRITICAL;
619         }
620         else if (cmin >= 0 && value < cmin) {
621                 return STATE_CRITICAL;
622         }
624         if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
625                 if (value > wmax && value < wmin) {
626                         return STATE_WARNING;
627                 }
628         }
629         else if (wmax >= 0 && value > wmax) {
630                 return STATE_WARNING;
631         }
632         else if (wmin >= 0 && value < wmin) {
633                 return STATE_WARNING;
634         }
635         return STATE_OK;
639 /* convert the elapsed time to seconds */
640 int
641 convert_to_seconds(char *etime) {
643         char *ptr;
644         int total;
646         int hyphcnt;
647         int coloncnt;
648         int days;
649         int hours;
650         int minutes;
651         int seconds;
653         hyphcnt = 0;
654         coloncnt = 0;
655         days = 0;
656         hours = 0;
657         minutes = 0;
658         seconds = 0;
660         for (ptr = etime; *ptr != '\0'; ptr++) {
661         
662                 if (*ptr == '-') {
663                         hyphcnt++;
664                         continue;
665                 }
666                 if (*ptr == ':') {
667                         coloncnt++;
668                         continue;
669                 }
670         }
672         if (hyphcnt > 0) {
673                 sscanf(etime, "%d-%d:%d:%d",
674                                 &days, &hours, &minutes, &seconds);
675                 /* linux 2.6.5/2.6.6 reporting some processes with infinite
676                  * elapsed times for some reason */
677                 if (days == 49710) {
678                         return 0;
679                 }
680         } else {
681                 if (coloncnt == 2) {
682                         sscanf(etime, "%d:%d:%d",
683                                 &hours, &minutes, &seconds);
684                 } else if (coloncnt == 1) {
685                         sscanf(etime, "%d:%d",
686                                 &minutes, &seconds);
687                 }
688         }
690         total = (days * 86400) +
691                 (hours * 3600) +
692                 (minutes * 60) +
693                 seconds;
695         if (verbose >= 3 && metric == METRIC_ELAPSED) {
696                         printf("seconds: %d\n", total);
697         }
698         return total;
702 void
703 print_help (void)
705         print_revision (progname, revision);
707         printf ("Copyright (c) 1999 Ethan Galstad <nagios@nagios.org>\n");
708         printf (COPYRIGHT, copyright, email);
710         printf ("%s\n", _("Checks all processes and generates WARNING or CRITICAL states if the specified"));
711   printf ("%s\n", _("metric is outside the required threshold ranges. The metric defaults to number"));
712   printf ("%s\n", _("of processes.  Search filters can be applied to limit the processes to check."));
714   printf ("\n\n");
715   
716         print_usage ();
718         printf ("%s\n", _("Required Arguments:"));
719   printf (" %s\n", "-w, --warning=RANGE");
720   printf ("   %s\n", _("Generate warning state if metric is outside this range"));
721   printf (" %s\n", "-c, --critical=RANGE");
722   printf ("   %s\n", _("Generate critical state if metric is outside this range"));
724         printf ("%s\n", _("Optional Arguments:"));
725   printf (" %s\n", "-m, --metric=TYPE");
726   printf ("  %s\n", _("Check thresholds against metric. Valid types:"));
727   printf ("  %s\n", _("PROCS   - number of processes (default)"));
728   printf ("  %s\n", _("VSZ     - virtual memory size"));
729   printf ("  %s\n", _("RSS     - resident set memory size"));
730   printf ("  %s\n", _("CPU     - percentage cpu"));
731 /* only linux etime is support currently */
732 #if defined( __linux__ )
733         printf ("  %s\n", _("ELAPSED - time elapsed in seconds"));
734 #endif /* defined(__linux__) */
735         printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
737         printf (" %s\n", "-v, --verbose");
738   printf ("    %s\n", _("Extra information. Up to 3 verbosity levels"));
740         printf ("%s\n", "Optional Filters:");
741   printf (" %s\n", "-s, --state=STATUSFLAGS");
742   printf ("   %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
743   printf ("   %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
744   printf ("   %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
745   printf (" %s\n", "-p, --ppid=PPID");
746   printf ("   %s\n", _("Only scan for children of the parent process ID indicated."));
747   printf (" %s\n", "-z, --vsz=VSZ");
748   printf ("   %s\n", _("Only scan for processes with vsz higher than indicated."));
749   printf (" %s\n", "-r, --rss=RSS");
750   printf ("   %s\n", _("Only scan for processes with rss higher than indicated."));
751         printf (" %s\n", "-P, --pcpu=PCPU");
752   printf ("   %s\n", _("Only scan for processes with pcpu higher than indicated."));
753   printf (" %s\n", "-u, --user=USER");
754   printf ("   %s\n", _("Only scan for processes with user name or ID indicated."));
755   printf (" %s\n", "-a, --argument-array=STRING");
756   printf ("   %s\n", _("Only scan for processes with args that contain STRING."));
757   printf (" %s\n", "--ereg-argument-array=STRING");
758   printf ("   %s\n", _("Only scan for processes with args that contain the regex STRING."));
759   printf (" %s\n", "-C, --command=COMMAND");
760   printf ("   %s\n", _("Only scan for exact matches of COMMAND (without path)."));
762         printf(_("\n\
763 RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n\
764 specified 'max:min', a warning status will be generated if the\n\
765 count is inside the specified range\n\n"));
767         printf(_("\
768 This plugin checks the number of currently running processes and\n\
769 generates WARNING or CRITICAL states if the process count is outside\n\
770 the specified threshold ranges. The process count can be filtered by\n\
771 process owner, parent process PID, current state (e.g., 'Z'), or may\n\
772 be the total number of running processes\n\n"));
774         printf ("%s\n", _("Examples:"));
775   printf (" %s\n", "check_procs -w 2:2 -c 2:1024 -C portsentry");
776   printf ("  %s\n", _("Warning if not two processes with command name portsentry."));
777   printf ("  %s\n\n", _("Critical if < 2 or > 1024 processes"));
778   printf (" %s\n", "check_procs -w 10 -a '/usr/local/bin/perl' -u root");
779   printf ("  %s\n", _("Warning alert if > 10 processes with command arguments containing"));
780   printf ("  %s\n\n", _("'/usr/local/bin/perl' and owned by root"));
781   printf (" %s\n", "check_procs -w 50000 -c 100000 --metric=VSZ");
782   printf ("  %s\n\n", _("Alert if vsz of any processes over 50K or 100K"));
783   printf (" %s\n", "check_procs -w 10 -c 20 --metric=CPU");
784   printf ("  %s\n\n", _("Alert if cpu of any processes over 10%% or 20%%"));
786         printf (_(UT_SUPPORT));
789 void
790 print_usage (void)
792   printf (_("Usage: "));
793         printf ("%s -w <range> -c <range> [-m metric] [-s state] [-p ppid]\n", progname);
794   printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
795   printf (" [-C command] [-t timeout] [-v]\n");