| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537 |
- /******************************************************************************
- *
- * CHECK_PROCS.C
- *
- * Program: Process plugin for Nagios
- * License: GPL
- * Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)
- *
- * $Id$
- *
- * Description:
- *
- * This plugin checks the number of currently running processes and
- * generates WARNING or CRITICAL states if the process count is outside
- * the specified threshold ranges. The process count can be filtered by
- * process owner, parent process PID, current state (e.g., 'Z'), or may
- * be the total number of running processes
- *
- * License Information:
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- ******************************************************************************/
- #include "config.h"
- #include <pwd.h>
- #include "common.h"
- #include "popen.h"
- #include "utils.h"
- int process_arguments (int, char **);
- int call_getopt (int, char **);
- int validate_arguments (void);
- void print_usage (void);
- void print_help (char *);
- int wmax = -1;
- int cmax = -1;
- int wmin = -1;
- int cmin = -1;
- int options = 0;
- #define ALL 1
- #define STAT 2
- #define PPID 4
- #define USER 8
- #define PROG 16
- #define ARGS 32
- int verbose = FALSE;
- int uid;
- int ppid;
- char *statopts = NULL;
- char *prog = NULL;
- char *args = NULL;
- char *format = NULL;
- char tmp[MAX_INPUT_BUFFER];
- int
- main (int argc, char **argv)
- {
- char input_buffer[MAX_INPUT_BUFFER];
- int procuid = 0;
- int procppid = 0;
- char procstat[8];
- char procprog[MAX_INPUT_BUFFER];
- char *procargs;
- int resultsum = 0;
- int found = 0;
- int procs = 0;
- int pos;
- int result = STATE_UNKNOWN;
- procargs = malloc (MAX_INPUT_BUFFER);
- if (process_arguments (argc, argv) == ERROR)
- usage ("Unable to parse command line\n");
- /* run the command */
- if (verbose)
- printf ("%s\n", PS_COMMAND);
- child_process = spopen (PS_COMMAND);
- if (child_process == NULL) {
- printf ("Could not open pipe: %s\n", PS_COMMAND);
- return STATE_UNKNOWN;
- }
- child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
- if (child_stderr == NULL)
- printf ("Could not open stderr for %s\n", PS_COMMAND);
- fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
- if (
- #ifdef USE_PS_VARS
- sscanf (input_buffer, PS_FORMAT, PS_VARLIST) >= 4
- #else
- sscanf (input_buffer, PS_FORMAT, procstat, &procuid, &procppid, &pos,
- procprog) >= 4
- #endif
- ) {
- found++;
- resultsum = 0;
- procargs = strcpy (procargs, &input_buffer[pos]);
- strip (procargs);
- if ((options & STAT) && (strstr (statopts, procstat)))
- resultsum |= STAT;
- if ((options & ARGS) && (strstr (procargs, args) == procargs))
- resultsum |= ARGS;
- if ((options & PROG) && (strcmp (prog, procprog) == 0))
- resultsum |= PROG;
- if ((options & PPID) && (procppid == ppid))
- resultsum |= PPID;
- if ((options & USER) && (procuid == uid))
- resultsum |= USER;
- #ifdef DEBUG1
- if (procargs == NULL)
- printf ("%d %d %d %s %s\n", procs, procuid, procppid, procstat,
- procprog);
- else
- printf ("%d %d %d %s %s %s\n", procs, procuid, procppid, procstat,
- procprog, procargs);
- #endif
- if (options == resultsum)
- procs++;
- }
- }
- /* If we get anything on STDERR, at least set warning */
- while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr)) {
- if (verbose)
- printf ("STDERR: %s", input_buffer);
- /*Cannot use max() any more as STATE_UNKNOWN is gt STATE_CRITICAL
- result = max (result, STATE_WARNING); */
- if ( !(result == STATE_CRITICAL) ) {
- result = STATE_WARNING;
- }
- printf ("System call sent warnings to stderr\n");
- }
-
- /* if (result == STATE_UNKNOWN || result == STATE_WARNING)
- printf ("System call sent warnings to stderr\n");
- */
- (void) fclose (child_stderr);
- /* close the pipe */
- if (spclose (child_process)) {
- printf ("System call returned nonzero status\n");
- if ( !(result == STATE_CRITICAL) ) {
- return STATE_WARNING;
- }
- else {
- return result ;
- }
- }
- if (options == ALL)
- procs = found;
- if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
- printf ("Unable to read output\n");
- return result;
- }
- if (verbose && (options & STAT))
- printf ("%s ", statopts);
- if (verbose && (options & PROG))
- printf ("%s ", prog);
- if (verbose && (options & PPID))
- printf ("%d ", ppid);
- if (verbose && (options & USER))
- printf ("%d ", uid);
- if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
- if (procs > cmax && procs < cmin) {
- printf (format, "CRITICAL", procs);
- return STATE_CRITICAL;
- }
- }
- else if (cmax >= 0 && procs > cmax) {
- printf (format, "CRITICAL", procs);
- return STATE_CRITICAL;
- }
- else if (cmin >= 0 && procs < cmin) {
- printf (format, "CRITICAL", procs);
- return STATE_CRITICAL;
- }
- if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
- if (procs > wmax && procs < wmin) {
- printf (format, "CRITICAL", procs);
- return STATE_CRITICAL;
- }
- }
- else if (wmax >= 0 && procs > wmax) {
- printf (format, "WARNING", procs);
- if ( !(result == STATE_CRITICAL) ) {
- return STATE_WARNING;
- }
- else {
- return result ;
- }
- /*return max (result, STATE_WARNING); */
- }
- else if (wmin >= 0 && procs < wmin) {
- printf (format, "WARNING", procs);
- if ( !(result == STATE_CRITICAL) ) {
- return STATE_WARNING;
- }
- else {
- return result ;
- }
- /*return max (result, STATE_WARNING); */
- }
- printf (format, "OK", procs);
- if ( result == STATE_UNKNOWN ) {
- result = STATE_OK;
- }
- return result;
- }
- /* process command-line arguments */
- int
- process_arguments (int argc, char **argv)
- {
- int c;
- if (argc < 2)
- return ERROR;
- for (c = 1; c < argc; c++)
- if (strcmp ("-to", argv[c]) == 0)
- strcpy (argv[c], "-t");
- c = 0;
- while (c += (call_getopt (argc - c, &argv[c]))) {
- if (argc <= c)
- break;
- if (wmax == -1)
- wmax = atoi (argv[c]);
- else if (cmax == -1)
- cmax = atoi (argv[c]);
- else if (statopts == NULL) {
- statopts = strscpy (statopts, argv[c]);
- format =
- strscat (format,
- ssprintf (NULL, "%sSTATE = %s", (options ? ", " : ""),
- statopts));
- options |= STAT;
- }
- }
- return validate_arguments ();
- }
- int
- call_getopt (int argc, char **argv)
- {
- int c, i = 1;
- char *user;
- struct passwd *pw;
- #ifdef HAVE_GETOPT_H
- int option_index = 0;
- static struct option long_options[] = {
- {"warning", required_argument, 0, 'w'},
- {"critical", required_argument, 0, 'c'},
- {"timeout", required_argument, 0, 't'},
- {"status", required_argument, 0, 's'},
- {"ppid", required_argument, 0, 'p'},
- {"command", required_argument, 0, 'C'},
- {"argument-array", required_argument, 0, 'a'},
- {"help", no_argument, 0, 'h'},
- {"version", no_argument, 0, 'V'},
- {"verbose", no_argument, 0, 'v'},
- {0, 0, 0, 0}
- };
- #endif
- while (1) {
- #ifdef HAVE_GETOPT_H
- c =
- getopt_long (argc, argv, "+Vvht:c:w:p:s:u:C:a:", long_options,
- &option_index);
- #else
- c = getopt (argc, argv, "+Vvht:c:w:p:s:u:C:a:");
- #endif
- if (c == EOF)
- break;
- i++;
- switch (c) {
- case 't':
- case 'c':
- case 'w':
- case 'p':
- case 's':
- case 'a':
- case 'u':
- case 'C':
- i++;
- }
- switch (c) {
- case '?': /* help */
- print_usage ();
- exit (STATE_UNKNOWN);
- case 'h': /* help */
- print_help (my_basename (argv[0]));
- exit (STATE_OK);
- case 'V': /* version */
- print_revision (my_basename (argv[0]), "$Revision$");
- exit (STATE_OK);
- case 't': /* timeout period */
- if (!is_integer (optarg)) {
- printf ("%s: Timeout Interval must be an integer!\n\n",
- my_basename (argv[0]));
- print_usage ();
- exit (STATE_UNKNOWN);
- }
- timeout_interval = atoi (optarg);
- break;
- case 'c': /* critical threshold */
- if (is_integer (optarg)) {
- cmax = atoi (optarg);
- break;
- }
- else if (sscanf (optarg, ":%d", &cmax) == 1) {
- break;
- }
- else if (sscanf (optarg, "%d:%d", &cmin, &cmax) == 2) {
- break;
- }
- else if (sscanf (optarg, "%d:", &cmin) == 1) {
- break;
- }
- else {
- printf ("%s: Critical Process Count must be an integer!\n\n",
- my_basename (argv[0]));
- print_usage ();
- exit (STATE_UNKNOWN);
- }
- case 'w': /* warning time threshold */
- if (is_integer (optarg)) {
- wmax = atoi (optarg);
- break;
- }
- else if (sscanf (optarg, ":%d", &wmax) == 1) {
- break;
- }
- else if (sscanf (optarg, "%d:%d", &wmin, &wmax) == 2) {
- break;
- }
- else if (sscanf (optarg, "%d:", &wmin) == 1) {
- break;
- }
- else {
- printf ("%s: Warning Process Count must be an integer!\n\n",
- my_basename (argv[0]));
- print_usage ();
- exit (STATE_UNKNOWN);
- }
- case 'p': /* process id */
- if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
- format =
- strscat (format,
- ssprintf (NULL, "%sPPID = %d", (options ? ", " : ""),
- ppid));
- options |= PPID;
- break;
- }
- printf ("%s: Parent Process ID must be an integer!\n\n",
- my_basename (argv[0]));
- print_usage ();
- exit (STATE_UNKNOWN);
- case 's': /* status */
- statopts = strscpy (statopts, optarg);
- format =
- strscat (format,
- ssprintf (NULL, "%sSTATE = %s", (options ? ", " : ""),
- statopts));
- options |= STAT;
- break;
- case 'u': /* user or user id */
- if (is_integer (optarg)) {
- uid = atoi (optarg);
- pw = getpwuid ((uid_t) uid);
- /* check to be sure user exists */
- if (pw == NULL) {
- printf ("UID %d was not found\n", uid);
- print_usage ();
- exit (STATE_UNKNOWN);
- }
- }
- else {
- pw = getpwnam (optarg);
- /* check to be sure user exists */
- if (pw == NULL) {
- printf ("User name %s was not found\n", optarg);
- print_usage ();
- exit (STATE_UNKNOWN);
- }
- /* then get uid */
- uid = pw->pw_uid;
- }
- user = pw->pw_name;
- format =
- strscat (format,
- ssprintf (NULL, "%sUID = %d (%s)", (options ? ", " : ""),
- uid, user));
- options |= USER;
- break;
- case 'C': /* command */
- prog = strscpy (prog, optarg);
- format =
- strscat (format,
- ssprintf (NULL, "%scommand name %s", (options ? ", " : ""),
- prog));
- options |= PROG;
- break;
- case 'a': /* args (full path name with args) */
- args = strscpy (args, optarg);
- format =
- strscat (format,
- ssprintf (NULL, "%sargs %s", (options ? ", " : ""), args));
- options |= ARGS;
- break;
- case 'v': /* command */
- verbose = TRUE;
- break;
- }
- }
- return i;
- }
- int
- validate_arguments ()
- {
- if (wmax >= 0 && wmin == -1)
- wmin = 0;
- if (cmax >= 0 && cmin == -1)
- cmin = 0;
- if (wmax >= wmin && cmax >= cmin) { /* standard ranges */
- if (wmax > cmax && cmax != -1) {
- printf ("wmax (%d) cannot be greater than cmax (%d)\n", wmax, cmax);
- return ERROR;
- }
- if (cmin > wmin && wmin != -1) {
- printf ("wmin (%d) cannot be less than cmin (%d)\n", wmin, cmin);
- return ERROR;
- }
- }
- if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
- printf ("At least one threshold must be set\n");
- return ERROR;
- }
- if (options == 0) {
- options = 1;
- format = ssprintf (format, "%%s - %%d processes running\n");
- }
- else {
- format =
- ssprintf (format, "%%s - %%d processes running with %s\n", format);
- }
- return options;
- }
- void
- print_help (char *cmd)
- {
- print_revision (cmd, "$Revision$");
- printf
- ("Copyright (c) 1999 Ethan Galstad (nagios@nagios.org)\n\n"
- "This plugin checks the number of currently running processes and\n"
- "generates WARNING or CRITICAL states if the process count is outside\n"
- "the specified threshold ranges. The process count can be filtered by\n"
- "process owner, parent process PID, current state (e.g., 'Z'), or may\n"
- "be the total number of running processes\n\n");
- print_usage ();
- printf
- ("\nRequired Arguments:\n"
- " -w, --warning=RANGE\n"
- " generate warning state if process count is outside this range\n"
- " -c, --critical=RANGE\n"
- " generate critical state if process count is outside this range\n\n"
- "Optional Filters:\n"
- " -s, --state=STATUSFLAGS\n"
- " Only scan for processes that have, in the output of `ps`, one or\n"
- " more of the status flags you specify (for example R, Z, S, RS,\n"
- " RSZDT, plus others based on the output of your 'ps' command).\n"
- " -p, --ppid=PPID\n"
- " Only scan for children of the parent process ID indicated.\n"
- " -u, --user=USER\n"
- " Only scan for proceses with user name or ID indicated.\n"
- " -a, --argument-array=STRING\n"
- " Only scan for ARGS that match up to the length of the given STRING\n"
- " -C, --command=COMMAND\n"
- " Only scan for exact matches to the named COMMAND.\n\n"
- "RANGEs are specified 'min:max' or 'min:' or ':max' (or 'max'). If\n"
- "specified 'max:min', a warning status will be generated if the\n"
- "count is inside the specified range\n");}
- void
- print_usage (void)
- {
- printf
- ("Usage:\n"
- " check_procs -w <range> -c <range> [-s state] [-p ppid] [-u user]\n"
- " [-a argument-array] [-C command]\n"
- " check_procs --version\n" " check_procs --help\n");
- }
|