/*****************************************************************************
*
* Nagios check_procs plugin
*
* License: GPL
* Copyright (c) 2000-2008 Nagios Plugins Development Team
*
* Last Modified: $Date$
*
* Description:
*
* This file contains the check_procs plugin
*
* Checks all processes and generates WARNING or CRITICAL states if the
* specified metric is outside the required threshold ranges. The metric
* defaults to number of processes. Search filters can be applied to limit
* the processes to check.
*
*
* 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 3 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, see .
*
* $Id$
*
*****************************************************************************/
const char *progname = "check_procs";
const char *program_name = "check_procs"; /* Required for coreutils libs */
const char *revision = "$Revision$";
const char *copyright = "2000-2008";
const char *email = "nagiosplug-devel@lists.sourceforge.net";
#include "common.h"
#include "utils.h"
#include "utils_cmd.h"
#include "regex.h"
#include "utils_base.h"
#include
int process_arguments (int, char **);
int validate_arguments (void);
int check_thresholds (int);
int convert_to_seconds (char *);
void print_help (void);
void print_usage (void);
void actions_on_failed_state (int, char*); /* Helper routine */
int wmax = -1;
int cmax = -1;
int wmin = -1;
int cmin = -1;
int options = 0; /* bitmask of filter criteria to test against */
#define ALL 1
#define STAT 2
#define PPID 4
#define USER 8
#define PROG 16
#define ARGS 32
#define VSZ 64
#define RSS 128
#define PCPU 256
#define ELAPSED 512
#define EREG_ARGS 1024
/* Different metrics */
char *metric_name;
enum metric {
NONE,
DEFAULT,
METRIC_PROCS,
METRIC_VSZ,
METRIC_RSS,
METRIC_CPU,
METRIC_ELAPSED
};
enum metric metric = DEFAULT;
enum metric default_metric = METRIC_PROCS;
int verbose = 0;
int uid;
pid_t ppid;
int vsz;
int rss;
float pcpu;
char *statopts;
char *prog;
char *args;
char *input_filename = NULL;
regex_t re_args;
char *fmt;
char *fails;
char tmp[MAX_INPUT_BUFFER];
FILE *ps_input = NULL;
thresholds *number_threshold = NULL;
thresholds *vsz_threshold = NULL;
thresholds *rss_threshold = NULL;
thresholds *cpu_threshold = NULL;
int new_style_thresholds = 0;
int warn = 0; /* number of processes in warn state */
int crit = 0; /* number of processes in crit state */
int result = STATE_UNKNOWN;
int
main (int argc, char **argv)
{
char *input_buffer;
char *input_line;
char *procprog;
char *last_critical = NULL;
char *last_warning = NULL;
char *last_failed_process = NULL;
pid_t mypid = 0;
int procuid = 0;
pid_t procpid = 0;
pid_t procppid = 0;
int procvsz = 0;
int procrss = 0;
int procseconds = 0;
float procpcpu = 0;
char procstat[8];
char procetime[MAX_INPUT_BUFFER] = { '\0' };
char *procargs;
const char *zombie = "Z";
int resultsum = 0; /* bitmask of the filter criteria met by a process */
int found = 0; /* counter for number of lines returned in `ps` output */
int procs = 0; /* counter for number of processes meeting filter criteria */
int pos; /* number of spaces before 'args' in `ps` output */
int cols; /* number of columns in ps output */
int expected_cols = PS_COLS - 1;
int i = 0, j = 0; /* Temporary values */
double rss_sum = 0;
double vsz_sum = 0;
double cpu_sum = 0;
double vsz_max = 0;
double rss_max = 0;
double cpu_max = 0;
int multiple_process_output_flag = 0;
int number_threshold_failure_flag = 0;
output chld_out, chld_err;
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
setlocale(LC_NUMERIC, "POSIX");
input_buffer = malloc (MAX_INPUT_BUFFER);
procprog = malloc (MAX_INPUT_BUFFER);
asprintf (&metric_name, "PROCS");
asprintf (&last_failed_process, "");
if (process_arguments (argc, argv) == ERROR)
usage4 (_("Could not parse arguments"));
/* get our pid */
mypid = getpid();
/* Set signal handling and alarm timeout */
if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
die (STATE_UNKNOWN, _("Cannot catch SIGALRM"));
}
(void) alarm ((unsigned) timeout_interval);
if (verbose >= 3)
printf (_("CMD: %s\n"), PS_COMMAND);
if (input_filename == NULL) {
result = cmd_run( PS_COMMAND, &chld_out, &chld_err, 0);
if (chld_err.lines > 0) {
printf ("%s: %s", _("System call sent warnings to stderr"), chld_err.line[0]);
exit(STATE_WARNING);
}
} else {
result = cmd_file_read( input_filename, &chld_out, 0);
}
/* flush first line: j starts at 1 */
for (j = 1; j < chld_out.lines; j++) {
input_line = chld_out.line[j];
if (verbose >= 3)
printf ("%s", input_line);
strcpy (procprog, "");
asprintf (&procargs, "%s", "");
cols = sscanf (input_line, PS_FORMAT, PS_VARLIST);
/* Zombie processes do not give a procprog command */
if ( cols < expected_cols && strstr(procstat, zombie) ) {
cols = expected_cols;
}
if ( cols >= expected_cols ) {
resultsum = 0;
asprintf (&procargs, "%s", input_line + pos);
strip (procargs);
/* Some ps return full pathname for command. This removes path */
strcpy(procprog, base_name(procprog));
/* we need to convert the elapsed time to seconds */
procseconds = convert_to_seconds(procetime);
if (verbose >= 3)
printf ("proc#=%d uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
procs, procuid, procvsz, procrss,
procpid, procppid, procpcpu, procstat,
procetime, procprog, procargs);
/* Ignore self */
if (mypid == procpid) continue;
/* Filter */
if ((options & STAT) && (strstr (statopts, procstat)))
resultsum |= STAT;
if ((options & ARGS) && procargs && (strstr (procargs, args) != NULL))
resultsum |= ARGS;
if ((options & EREG_ARGS) && procargs && (regexec(&re_args, procargs, (size_t) 0, NULL, 0) == 0))
resultsum |= EREG_ARGS;
if ((options & PROG) && procprog && (strcmp (prog, procprog) == 0))
resultsum |= PROG;
if ((options & PPID) && (procppid == ppid))
resultsum |= PPID;
if ((options & USER) && (procuid == uid))
resultsum |= USER;
if ((options & VSZ) && (procvsz >= vsz))
resultsum |= VSZ;
if ((options & RSS) && (procrss >= rss))
resultsum |= RSS;
if ((options & PCPU) && (procpcpu >= pcpu))
resultsum |= PCPU;
found++;
/* Next line if filters not matched */
if (!(options == resultsum || options == ALL))
continue;
procs++;
if (verbose >= 3) {
printf ("Matched: uid=%d vsz=%d rss=%d pid=%d ppid=%d pcpu=%.2f stat=%s etime=%s prog=%s args=%s\n",
procuid, procvsz, procrss,
procpid, procppid, procpcpu, procstat,
procetime, procprog, procargs);
}
/* Check against metric - old style single check */
if (metric == METRIC_VSZ) {
actions_on_failed_state( check_thresholds (procvsz), procprog );
} else if (metric == METRIC_RSS) {
actions_on_failed_state( check_thresholds (procrss), procprog );
/* TODO? float thresholds for --metric=CPU */
} else if (metric == METRIC_CPU) {
actions_on_failed_state( check_thresholds ((int)procpcpu), procprog );
} else if (metric == METRIC_ELAPSED) {
actions_on_failed_state( check_thresholds (procseconds), procprog );
}
asprintf( &last_critical, "" );
asprintf( &last_warning, "" );
/* Check against all new style thresholds */
if (vsz_threshold != NULL) {
if ((i = get_status( procvsz, vsz_threshold )) != STATE_OK ) {
actions_on_failed_state(i, procprog);
asprintf( &last_failed_process, "%s", procprog );
if (i == STATE_CRITICAL) {
asprintf( &last_critical, "vsz=%d", procvsz );
} else if (i == STATE_WARNING) {
asprintf( &last_warning, "vsz=%d", procvsz );
}
if (verbose >= 2) {
printf("VSZ state %d: proc=%s vsz=%d ", i, procprog, procvsz);
print_thresholds( vsz_threshold );
}
}
}
if (rss_threshold != NULL) {
if ((i = get_status( procrss, rss_threshold )) != STATE_OK ) {
actions_on_failed_state(i, procprog);
asprintf( &last_failed_process, "%s", procprog );
if (i == STATE_CRITICAL) {
asprintf( &last_critical, "%s%srss=%d", last_critical, (strcmp(last_critical,"") ? ", " : ""), procrss );
} else if (i == STATE_WARNING) {
asprintf( &last_warning, "%s%srss=%d", last_warning, (strcmp(last_warning,"") ? ", " : ""), procrss );
}
if (verbose >= 2) {
printf("RSS: proc=%s rss=%d ", procprog, procrss);
print_thresholds( rss_threshold );
}
}
}
if (cpu_threshold != NULL) {
if (( i = get_status( procpcpu, cpu_threshold )) != STATE_OK ) {
actions_on_failed_state(i, procprog);
asprintf( &last_failed_process, "%s", procprog );
if (i == STATE_CRITICAL) {
asprintf( &last_critical, "%s%scpu=%.2f%%", last_critical, (strcmp(last_critical,"") ? ", " : ""), procpcpu );
} else if (i == STATE_WARNING) {
asprintf( &last_warning, "%s%scpu=%.2f%%", last_warning, (strcmp(last_warning,"") ? ", " : ""), procpcpu );
}
if (verbose >= 2) {
printf("CPU: proc=%s cpu=%f ", procprog, procpcpu);
print_thresholds( cpu_threshold );
}
}
}
/* Summary information */
rss_sum += procrss;
vsz_sum += procvsz;
cpu_sum += procpcpu;
if (procrss > rss_max)
rss_max = procrss;
if (procvsz > vsz_max)
vsz_max = procvsz;
if (procpcpu > cpu_max)
cpu_max = procpcpu;
}
/* This should not happen */
else if (verbose) {
printf(_("Not parseable: %s"), input_buffer);
}
}
if (found == 0) { /* no process lines parsed so return STATE_UNKNOWN */
printf (_("Unable to read output\n"));
return STATE_UNKNOWN;
}
if ( result == STATE_UNKNOWN )
result = STATE_OK;
/* Needed if procs found, but none match filter */
if ( metric == METRIC_PROCS ) {
result = max_state (result, i = check_thresholds (procs) );
}
if (number_threshold != NULL) {
if (i = get_status( procs, number_threshold ) != STATE_OK) {
actions_on_failed_state(i, "NUMBER_OF_PROCESSES");
if (verbose >= 2) {
printf("NUMBER: total_procs=%d ", procs);
print_thresholds( number_threshold );
}
number_threshold_failure_flag = 1;
}
}
if ( result == STATE_OK ) {
printf ("%s %s: ", metric_name, _("OK"));
multiple_process_output_flag = 1;
} else if (result == STATE_WARNING) {
printf ("%s %s: ", metric_name, _("WARNING"));
if (procs == 1 && new_style_thresholds && ! number_threshold_failure_flag) {
printf("%s: warning %s", last_failed_process, last_warning);
} else {
if ( metric != METRIC_PROCS ) {
printf (_("Alerts: %d warn from "), warn);
}
multiple_process_output_flag = 1;
}
} else if (result == STATE_CRITICAL) {
printf ("%s %s: ", metric_name, _("CRITICAL"));
if (procs == 1 && new_style_thresholds && ! number_threshold_failure_flag) {
printf("%s: critical %s", last_failed_process, last_critical);
if (strcmp(last_warning, "")) {
printf("; warning %s", last_warning);
}
} else {
if (metric != METRIC_PROCS) {
printf (_("Alerts: %d crit, %d warn from "), crit, warn);
}
multiple_process_output_flag = 1;
}
}
if (multiple_process_output_flag) {
printf (ngettext ("%d process", "%d processes", (unsigned long) procs), procs);
if (strcmp(fmt,"") != 0) {
printf (_(" with %s"), fmt);
}
if ( verbose >= 1 && strcmp(fails,"") )
printf (" [%s]", fails);
}
printf(" | ");
if( number_threshold != NULL)
printf("number=%d ", procs);
if (procs > 0) {
if( vsz_threshold != NULL)
printf("vsz=%.0f ", vsz_sum/procs);
if( rss_threshold != NULL)
printf("rss=%.0f ", rss_sum/procs);
if( cpu_threshold != NULL)
printf("cpu=%.2f ", cpu_sum/procs);
}
printf ("\n");
return result;
}
/* process command-line arguments */
int
process_arguments (int argc, char **argv)
{
int c = 1;
char *user;
struct passwd *pw;
int option = 0;
int err;
int cflags = REG_NOSUB | REG_EXTENDED;
char errbuf[MAX_INPUT_BUFFER];
static struct option longopts[] = {
{"warning", required_argument, 0, 'w'},
{"critical", required_argument, 0, 'c'},
{"metric", required_argument, 0, 'm'},
{"timeout", required_argument, 0, 't'},
{"status", required_argument, 0, 's'},
{"ppid", required_argument, 0, 'p'},
{"command", required_argument, 0, 'C'},
{"vsz", required_argument, 0, 'z'},
{"rss", required_argument, 0, 'r'},
{"pcpu", required_argument, 0, 'P'},
{"elapsed", required_argument, 0, 'e'},
{"argument-array", required_argument, 0, 'a'},
{"help", no_argument, 0, 'h'},
{"version", no_argument, 0, 'V'},
{"verbose", no_argument, 0, 'v'},
{"ereg-argument-array", required_argument, 0, CHAR_MAX+1},
{"input-file", required_argument, 0, CHAR_MAX+2},
{"number", optional_argument, 0, CHAR_MAX+3},
{"rss-threshold", optional_argument, 0, CHAR_MAX+4},
/*
{"rss-max", optional_argument, 0, CHAR_MAX+5},
{"rss-sum", optional_argument, 0, CHAR_MAX+6},
*/
{"vsz-threshold", optional_argument, 0, CHAR_MAX+7},
/*
{"vsz-max", optional_argument, 0, CHAR_MAX+8},
{"vsz-sum", optional_argument, 0, CHAR_MAX+9},
*/
{"cpu-threshold", optional_argument, 0, CHAR_MAX+10},
/*
{"cpu-max", optional_argument, 0, CHAR_MAX+11},
{"cpu-sum", optional_argument, 0, CHAR_MAX+12},
*/
{0, 0, 0, 0}
};
for (c = 1; c < argc; c++)
if (strcmp ("-to", argv[c]) == 0)
strcpy (argv[c], "-t");
while (1) {
c = getopt_long (argc, argv, "Vvht:c:w:p:s:u:C:a:z:r:m:P:",
longopts, &option);
if (c == -1 || c == EOF)
break;
switch (c) {
case '?': /* help */
usage5 ();
case 'h': /* help */
print_help ();
exit (STATE_OK);
case 'V': /* version */
print_revision (progname, revision);
exit (STATE_OK);
case 't': /* timeout period */
if (!is_integer (optarg))
usage2 (_("Timeout interval must be a positive integer"), optarg);
else
timeout_interval = atoi (optarg);
break;
case 'c': /* critical threshold */
if (is_integer (optarg))
cmax = atoi (optarg);
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
usage4 (_("Critical Process Count must be an integer!"));
break;
case 'w': /* warning threshold */
if (is_integer (optarg))
wmax = atoi (optarg);
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
usage4 (_("Warning Process Count must be an integer!"));
break;
case 'p': /* process id */
if (sscanf (optarg, "%d%[^0-9]", &ppid, tmp) == 1) {
asprintf (&fmt, "%s%sPPID = %d", (fmt ? fmt : "") , (options ? ", " : ""), ppid);
options |= PPID;
break;
}
usage4 (_("Parent Process ID must be an integer!"));
case 's': /* status */
if (statopts)
break;
else
statopts = optarg;
asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (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)
usage2 (_("UID was not found"), optarg);
}
else {
pw = getpwnam (optarg);
/* check to be sure user exists */
if (pw == NULL)
usage2 (_("User name was not found"), optarg);
/* then get uid */
uid = pw->pw_uid;
}
user = pw->pw_name;
asprintf (&fmt, "%s%sUID = %d (%s)", (fmt ? fmt : ""), (options ? ", " : ""),
uid, user);
options |= USER;
break;
case 'C': /* command */
/* TODO: allow this to be passed in with --metric */
if (prog)
break;
else
prog = optarg;
asprintf (&fmt, _("%s%scommand name '%s'"), (fmt ? fmt : ""), (options ? ", " : ""),
prog);
options |= PROG;
break;
case 'a': /* args (full path name with args) */
/* TODO: allow this to be passed in with --metric */
if (args)
break;
else
args = optarg;
asprintf (&fmt, "%s%sargs '%s'", (fmt ? fmt : ""), (options ? ", " : ""), args);
options |= ARGS;
break;
case CHAR_MAX+1:
err = regcomp(&re_args, optarg, cflags);
if (err != 0) {
regerror (err, &re_args, errbuf, MAX_INPUT_BUFFER);
die (STATE_UNKNOWN, "PROCS %s: %s - %s\n", _("UNKNOWN"), _("Could not compile regular expression"), errbuf);
}
asprintf (&fmt, "%s%sregex args '%s'", (fmt ? fmt : ""), (options ? ", " : ""), optarg);
options |= EREG_ARGS;
break;
case 'r': /* RSS */
if (sscanf (optarg, "%d%[^0-9]", &rss, tmp) == 1) {
asprintf (&fmt, "%s%sRSS >= %d", (fmt ? fmt : ""), (options ? ", " : ""), rss);
options |= RSS;
break;
}
usage4 (_("RSS must be an integer!"));
case 'z': /* VSZ */
if (sscanf (optarg, "%d%[^0-9]", &vsz, tmp) == 1) {
asprintf (&fmt, "%s%sVSZ >= %d", (fmt ? fmt : ""), (options ? ", " : ""), vsz);
options |= VSZ;
break;
}
usage4 (_("VSZ must be an integer!"));
case 'P': /* PCPU */
/* TODO: -P 1.5.5 is accepted */
if (sscanf (optarg, "%f%[^0-9.]", &pcpu, tmp) == 1) {
asprintf (&fmt, "%s%sPCPU >= %.2f", (fmt ? fmt : ""), (options ? ", " : ""), pcpu);
options |= PCPU;
break;
}
usage4 (_("PCPU must be a float!"));
case 'm':
asprintf (&metric_name, "%s", optarg);
if ( strcmp(optarg, "PROCS") == 0) {
metric = METRIC_PROCS;
break;
}
else if ( strcmp(optarg, "VSZ") == 0) {
metric = METRIC_VSZ;
break;
}
else if ( strcmp(optarg, "RSS") == 0 ) {
metric = METRIC_RSS;
break;
}
else if ( strcmp(optarg, "CPU") == 0 ) {
metric = METRIC_CPU;
break;
}
else if ( strcmp(optarg, "ELAPSED") == 0) {
metric = METRIC_ELAPSED;
break;
}
usage4 (_("Metric must be one of PROCS, VSZ, RSS, CPU, ELAPSED!"));
case 'v': /* command */
verbose++;
break;
case CHAR_MAX+2:
input_filename = optarg;
break;
case CHAR_MAX+3:
number_threshold = parse_thresholds_string(optarg);
if (metric == DEFAULT)
default_metric=NONE;
break;
case CHAR_MAX+4:
rss_threshold = parse_thresholds_string(optarg);
new_style_thresholds++;
if (metric == DEFAULT)
default_metric=NONE;
break;
case CHAR_MAX+7:
vsz_threshold = parse_thresholds_string(optarg);
new_style_thresholds++;
if (metric == DEFAULT)
default_metric=NONE;
break;
case CHAR_MAX+10:
cpu_threshold = parse_thresholds_string(optarg);
new_style_thresholds++;
if (metric == DEFAULT)
default_metric=NONE;
break;
}
}
c = optind;
if (wmax == -1 && argv[c])
wmax = atoi (argv[c++]);
if (cmax == -1 && argv[c])
cmax = atoi (argv[c++]);
if (statopts == NULL && argv[c]) {
asprintf (&statopts, "%s", argv[c++]);
asprintf (&fmt, _("%s%sSTATE = %s"), (fmt ? fmt : ""), (options ? ", " : ""), statopts);
options |= STAT;
}
return validate_arguments ();
}
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 = ALL;
if (statopts==NULL)
statopts = strdup("");
if (prog==NULL)
prog = strdup("");
if (args==NULL)
args = strdup("");
if (fmt==NULL)
fmt = strdup("");
if (fails==NULL)
fails = strdup("");
if (metric==DEFAULT)
metric = default_metric;
return options;
}
/* Check thresholds against value */
int
check_thresholds (int value)
{
if (wmax == -1 && cmax == -1 && wmin == -1 && cmin == -1) {
return OK;
}
else if (cmax >= 0 && cmin >= 0 && cmax < cmin) {
if (value > cmax && value < cmin)
return STATE_CRITICAL;
}
else if (cmax >= 0 && value > cmax) {
return STATE_CRITICAL;
}
else if (cmin >= 0 && value < cmin) {
return STATE_CRITICAL;
}
if (wmax >= 0 && wmin >= 0 && wmax < wmin) {
if (value > wmax && value < wmin) {
return STATE_WARNING;
}
}
else if (wmax >= 0 && value > wmax) {
return STATE_WARNING;
}
else if (wmin >= 0 && value < wmin) {
return STATE_WARNING;
}
return STATE_OK;
}
void
actions_on_failed_state(int state, char *procprog) {
result = max_state (result, state);
if (state != STATE_WARNING && state != STATE_CRITICAL)
return;
if (state == STATE_WARNING) {
warn++;
}
if (state == STATE_CRITICAL) {
crit++;
}
/* TODO: This should be a hash, to remove duplicates */
asprintf (&fails, "%s%s%s", fails, (strcmp(fails,"") ? ", " : ""), procprog);
}
/* convert the elapsed time to seconds */
int
convert_to_seconds(char *etime) {
char *ptr;
int total;
int hyphcnt;
int coloncnt;
int days;
int hours;
int minutes;
int seconds;
hyphcnt = 0;
coloncnt = 0;
days = 0;
hours = 0;
minutes = 0;
seconds = 0;
for (ptr = etime; *ptr != '\0'; ptr++) {
if (*ptr == '-') {
hyphcnt++;
continue;
}
if (*ptr == ':') {
coloncnt++;
continue;
}
}
if (hyphcnt > 0) {
sscanf(etime, "%d-%d:%d:%d",
&days, &hours, &minutes, &seconds);
/* linux 2.6.5/2.6.6 reporting some processes with infinite
* elapsed times for some reason */
if (days == 49710) {
return 0;
}
} else {
if (coloncnt == 2) {
sscanf(etime, "%d:%d:%d",
&hours, &minutes, &seconds);
} else if (coloncnt == 1) {
sscanf(etime, "%d:%d",
&minutes, &seconds);
}
}
total = (days * 86400) +
(hours * 3600) +
(minutes * 60) +
seconds;
if (verbose >= 3 && metric == METRIC_ELAPSED) {
printf("seconds: %d\n", total);
}
return total;
}
void
print_help (void)
{
print_revision (progname, revision);
printf ("Copyright (c) 1999 Ethan Galstad \n");
printf (COPYRIGHT, copyright, email);
print_usage ();
printf ("\n\n");
printf("Checks all processes and, optionally, filters to a subset to check thresholds values against.\n");
printf("Can specify any of the following thresholds:\n");
printf(" --number=THRESHOLD - Compares the number of matching processes\n");
printf(" --vsz-threshold=THRESHOLD - Compares each process' vsz (in kilobytes)\n");
printf(" --rss-threshold=THRESHOLD - Compares each process' rss (in kilobytes)\n");
printf(" --cpu-threshold=THRESHOLD - Compares each process' cpu (in %%)\n");
/* TODO: Add support for etime */
printf("\n\n");
printf ("%s\n", _("Optional Arguments:"));
printf (_(UT_TIMEOUT), DEFAULT_SOCKET_TIMEOUT);
printf (" %s\n", "-v, --verbose");
printf (" %s\n", _("Extra information. Up to 3 verbosity levels"));
printf ("%s\n", "Optional Filters:");
printf (" %s\n", "-s, --state=STATUSFLAGS");
printf (" %s\n", _("Only scan for processes that have, in the output of `ps`, one or"));
printf (" %s\n", _("more of the status flags you specify (for example R, Z, S, RS,"));
printf (" %s\n", _("RSZDT, plus others based on the output of your 'ps' command)."));
printf (" %s\n", "-p, --ppid=PPID");
printf (" %s\n", _("Only scan for children of the parent process ID indicated."));
printf (" %s\n", "-z, --vsz=VSZ");
printf (" %s\n", _("Only scan for processes with vsz higher than indicated."));
printf (" %s\n", "-r, --rss=RSS");
printf (" %s\n", _("Only scan for processes with rss higher than indicated."));
printf (" %s\n", "-P, --pcpu=PCPU");
printf (" %s\n", _("Only scan for processes with pcpu higher than indicated."));
printf (" %s\n", "-u, --user=USER");
printf (" %s\n", _("Only scan for processes with user name or ID indicated."));
printf (" %s\n", "-a, --argument-array=STRING");
printf (" %s\n", _("Only scan for processes with args that contain STRING."));
printf (" %s\n", "--ereg-argument-array=STRING");
printf (" %s\n", _("Only scan for processes with args that contain the regex STRING."));
printf (" %s\n", "-C, --command=COMMAND");
printf (" %s\n", _("Only scan for exact matches of COMMAND (without path)."));
printf("\n");
printf("\
THRESHOLDS are specified as 'critical_range/warning_range' where\n\
RANGES are defined as 'min:max'. max can be removed if it is infinity.\n\
Alerts will occur inside this range, unless you specify '^' before\n\
the range, to mean alert outside this range\n\n");
printf ("%s\n", _("Examples:"));
printf (" %s\n", "check_procs --number=:2/5: -C portsentry");
printf (" %s\n", _("Warning if greater than five processes with command name portsentry."));
printf (" %s\n\n", _("Critical if <= 2 processes"));
printf (" %s\n", "check_procs --vsz-threshold=100:/50:");
printf (" %s\n\n", _("Warning if vsz of any processes is over 50K or critical if vsz is over 100K"));
printf (" %s\n", "check_procs --cpu-threshold=20:/10: --ereg-argument-array='java.*server'");
printf (" %s\n\n", _("For all processes with arguments matching the regular expression, warning if cpu is over 10% or critical if over 20%"));
printf (" %s\n", "check_procs --rss-threshold=100: --number=/:10 --cpu-threshold=30:/10: -a '/usr/local/bin/perl' -u root");
printf (" %s\n", _("Critical if rss >= 100K, or warning if total number of process <= 10, or critical if cpu >= 30% or warning if cpu >= 10%."));
printf (" %s\n", _("Filter by arguments containing '/usr/local/bin/perl' and owned by root"));
printf (_(UT_SUPPORT));
}
void
print_usage (void)
{
printf (_("Usage: "));
printf ("%s -w -c [-m metric] [-s state] [-p ppid]\n", progname);
printf (" [-u user] [-r rss] [-z vsz] [-P %%cpu] [-a argument-array]\n");
printf (" [-C command] [-t timeout] [-v]\n");
}