Refactor check_nagios

This commit is contained in:
Lorenz Kästle 2025-03-11 16:18:03 +01:00
parent bc003d5e2e
commit b16360eede
3 changed files with 88 additions and 64 deletions

View file

@ -53,6 +53,7 @@ EXTRA_DIST = t \
check_ldap.d \
check_hpjd.d \
check_game.d \
check_nagios.d \
check_dbi.d \
check_ssh.d \
check_dns.d \

View file

@ -39,47 +39,20 @@ const char *email = "devel@monitoring-plugins.org";
#include "common.h"
#include "runcmd.h"
#include "utils.h"
#include "states.h"
#include "check_nagios.d/config.h"
static int process_arguments(int /*argc*/, char ** /*argv*/);
typedef struct {
int errorcode;
check_nagios_config config;
} check_nagios_config_wrapper;
static check_nagios_config_wrapper process_arguments(int /*argc*/, char ** /*argv*/);
static void print_help(void);
void print_usage(void);
static char *status_log = NULL;
static char *process_string = NULL;
static int expire_minutes = 0;
static int verbose = 0;
int main(int argc, char **argv) {
int result = STATE_UNKNOWN;
char input_buffer[MAX_INPUT_BUFFER];
unsigned long latest_entry_time = 0L;
unsigned long temp_entry_time = 0L;
int proc_entries = 0;
time_t current_time;
char *temp_ptr;
FILE *fp;
int procuid = 0;
int procpid = 0;
int procppid = 0;
int procvsz = 0;
int procrss = 0;
float procpcpu = 0;
char procstat[8];
#ifdef PS_USES_PROCETIME
char procetime[MAX_INPUT_BUFFER];
#endif /* PS_USES_PROCETIME */
char procprog[MAX_INPUT_BUFFER];
char *procargs;
int pos;
int cols;
int expected_cols = PS_COLS - 1;
const char *zombie = "Z";
char *temp_string;
output chld_out;
output chld_err;
size_t i;
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
@ -87,10 +60,14 @@ int main(int argc, char **argv) {
/* Parse extra opts if any */
argv = np_extra_opts(&argc, argv, progname);
if (process_arguments(argc, argv) == ERROR) {
check_nagios_config_wrapper tmp_config = process_arguments(argc, argv);
if (tmp_config.errorcode == ERROR) {
usage_va(_("Could not parse arguments"));
}
const check_nagios_config config = tmp_config.config;
/* Set signal handling and alarm timeout */
if (signal(SIGALRM, timeout_alarm_handler) == SIG_ERR) {
usage_va(_("Cannot catch SIGALRM"));
@ -100,13 +77,17 @@ int main(int argc, char **argv) {
alarm(timeout_interval);
/* open the status log */
fp = fopen(status_log, "r");
if (fp == NULL) {
FILE *log_file = fopen(config.status_log, "r");
if (log_file == NULL) {
die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
}
unsigned long latest_entry_time = 0L;
unsigned long temp_entry_time = 0L;
char input_buffer[MAX_INPUT_BUFFER];
char *temp_ptr;
/* get the date/time of the last item updated in the log */
while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
while (fgets(input_buffer, MAX_INPUT_BUFFER - 1, log_file)) {
if ((temp_ptr = strstr(input_buffer, "created=")) != NULL) {
temp_entry_time = strtoul(temp_ptr + 8, NULL, 10);
latest_entry_time = temp_entry_time;
@ -119,20 +100,39 @@ int main(int argc, char **argv) {
}
}
}
fclose(fp);
fclose(log_file);
if (verbose >= 2) {
printf("command: %s\n", PS_COMMAND);
}
/* run the command to check for the Nagios process.. */
mp_state_enum result = STATE_UNKNOWN;
output chld_out;
output chld_err;
if ((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0) {
result = STATE_WARNING;
}
int procuid = 0;
int procpid = 0;
int procppid = 0;
int procvsz = 0;
int procrss = 0;
int proc_entries = 0;
float procpcpu = 0;
char procstat[8];
char procprog[MAX_INPUT_BUFFER];
char *procargs;
#ifdef PS_USES_PROCETIME
char procetime[MAX_INPUT_BUFFER];
#endif /* PS_USES_PROCETIME */
int pos;
int expected_cols = PS_COLS - 1;
const char *zombie = "Z";
/* count the number of matching Nagios processes... */
for (i = 0; i < chld_out.lines; i++) {
cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
for (size_t i = 0; i < chld_out.lines; i++) {
int cols = sscanf(chld_out.line[i], PS_FORMAT, PS_VARLIST);
/* Zombie processes do not give a procprog command */
if (cols == (expected_cols - 1) && strstr(procstat, zombie)) {
cols = expected_cols;
@ -146,14 +146,14 @@ int main(int argc, char **argv) {
strip(procargs);
/* Some ps return full pathname for command. This removes path */
temp_string = strtok((char *)procprog, "/");
char *temp_string = strtok((char *)procprog, "/");
while (temp_string) {
strcpy(procprog, temp_string);
temp_string = strtok(NULL, "/");
}
/* May get empty procargs */
if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs, "")) {
if (!strstr(procargs, argv[0]) && strstr(procargs, config.process_string) && strcmp(procargs, "")) {
proc_entries++;
if (verbose >= 2) {
printf(_("Found process: %s %s\n"), procprog, procargs);
@ -178,8 +178,9 @@ int main(int argc, char **argv) {
die(STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
}
time_t current_time;
time(&current_time);
if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
if ((int)(current_time - latest_entry_time) > (config.expire_minutes * 60)) {
result = STATE_WARNING;
} else {
result = STATE_OK;
@ -192,42 +193,45 @@ int main(int argc, char **argv) {
(int)(current_time - latest_entry_time));
printf("\n");
return result;
exit(result);
}
/* process command-line arguments */
int process_arguments(int argc, char **argv) {
int c;
int option = 0;
check_nagios_config_wrapper process_arguments(int argc, char **argv) {
static struct option longopts[] = {{"filename", required_argument, 0, 'F'}, {"expires", required_argument, 0, 'e'},
{"command", required_argument, 0, 'C'}, {"timeout", optional_argument, 0, 't'},
{"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'},
{"verbose", no_argument, 0, 'v'}, {0, 0, 0, 0}};
check_nagios_config_wrapper result = {
.errorcode = OK,
.config = check_nagios_config_init(),
};
if (argc < 2) {
return ERROR;
result.errorcode = ERROR;
return result;
}
if (!is_option(argv[1])) {
status_log = argv[1];
result.config.status_log = argv[1];
if (is_intnonneg(argv[2])) {
expire_minutes = atoi(argv[2]);
result.config.expire_minutes = atoi(argv[2]);
} else {
die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
}
process_string = argv[3];
return OK;
result.config.process_string = argv[3];
return result;
}
while (1) {
c = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
int option = 0;
while (true) {
int option_index = getopt_long(argc, argv, "+hVvF:C:e:t:", longopts, &option);
if (c == -1 || c == EOF || c == 1) {
if (option_index == -1 || option_index == EOF || option_index == 1) {
break;
}
switch (c) {
switch (option_index) {
case 'h': /* help */
print_help();
exit(STATE_UNKNOWN);
@ -235,14 +239,14 @@ int process_arguments(int argc, char **argv) {
print_revision(progname, NP_VERSION);
exit(STATE_UNKNOWN);
case 'F': /* status log */
status_log = optarg;
result.config.status_log = optarg;
break;
case 'C': /* command */
process_string = optarg;
result.config.process_string = optarg;
break;
case 'e': /* expiry time */
if (is_intnonneg(optarg)) {
expire_minutes = atoi(optarg);
result.config.expire_minutes = atoi(optarg);
} else {
die(STATE_UNKNOWN, _("Expiration time must be an integer (seconds)\n"));
}
@ -262,15 +266,15 @@ int process_arguments(int argc, char **argv) {
}
}
if (status_log == NULL) {
if (result.config.status_log == NULL) {
die(STATE_UNKNOWN, _("You must provide the status_log\n"));
}
if (process_string == NULL) {
if (result.config.process_string == NULL) {
die(STATE_UNKNOWN, _("You must provide a process string\n"));
}
return OK;
return result;
}
void print_help(void) {

View file

@ -0,0 +1,19 @@
#pragma once
#include "../../config.h"
#include <stddef.h>
typedef struct {
char *status_log;
char *process_string;
int expire_minutes;
} check_nagios_config;
check_nagios_config check_nagios_config_init() {
check_nagios_config tmp = {
.status_log = NULL,
.process_string = NULL,
.expire_minutes = 0,
};
return tmp;
}