Merge remote-tracking branch 'upstream/pr/1456'
[monitoring-plugins.git] / plugins / check_nagios.c
blob40d68f03d8299ed8f027a19df193f21ed2cd0cd0
1 /*****************************************************************************
2 *
3 * Monitoring check_nagios plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2007 Monitoring Plugins Development Team
7 *
8 * Description:
9 *
10 * This file contains the check_nagios plugin
12 * This plugin checks the status of the Nagios process on the local machine.
13 * The plugin will check to make sure the Nagios status log is no older than
14 * the number of minutes specified by the expires option.
15 * It also checks the process table for a process matching the command
16 * argument.
19 * This program is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License as published by
21 * the Free Software Foundation, either version 3 of the License, or
22 * (at your option) any later version.
24 * This program is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
27 * GNU General Public License for more details.
29 * You should have received a copy of the GNU General Public License
30 * along with this program. If not, see <http://www.gnu.org/licenses/>.
33 *****************************************************************************/
35 const char *progname = "check_nagios";
36 const char *copyright = "1999-2007";
37 const char *email = "devel@monitoring-plugins.org";
39 #include "common.h"
40 #include "runcmd.h"
41 #include "utils.h"
43 int process_arguments (int, char **);
44 void print_help (void);
45 void print_usage (void);
47 char *status_log = NULL;
48 char *process_string = NULL;
49 int expire_minutes = 0;
51 int verbose = 0;
53 int
54 main (int argc, char **argv)
56 int result = STATE_UNKNOWN;
57 char input_buffer[MAX_INPUT_BUFFER];
58 unsigned long latest_entry_time = 0L;
59 unsigned long temp_entry_time = 0L;
60 int proc_entries = 0;
61 time_t current_time;
62 char *temp_ptr;
63 FILE *fp;
64 int procuid = 0;
65 int procpid = 0;
66 int procppid = 0;
67 int procvsz = 0;
68 int procrss = 0;
69 float procpcpu = 0;
70 char procstat[8];
71 #ifdef PS_USES_PROCETIME
72 char procetime[MAX_INPUT_BUFFER];
73 #endif /* PS_USES_PROCETIME */
74 char procprog[MAX_INPUT_BUFFER];
75 char *procargs;
76 int pos, cols;
77 int expected_cols = PS_COLS - 1;
78 const char *zombie = "Z";
79 char *temp_string;
80 output chld_out, chld_err;
81 size_t i;
83 setlocale (LC_ALL, "");
84 bindtextdomain (PACKAGE, LOCALEDIR);
85 textdomain (PACKAGE);
87 /* Parse extra opts if any */
88 argv=np_extra_opts (&argc, argv, progname);
90 if (process_arguments (argc, argv) == ERROR)
91 usage_va(_("Could not parse arguments"));
93 /* Set signal handling and alarm timeout */
94 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
95 usage_va(_("Cannot catch SIGALRM"));
98 /* handle timeouts gracefully... */
99 alarm (timeout_interval);
101 /* open the status log */
102 fp = fopen (status_log, "r");
103 if (fp == NULL) {
104 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
107 /* get the date/time of the last item updated in the log */
108 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
109 if ((temp_ptr = strstr (input_buffer, "created=")) != NULL) {
110 temp_entry_time = strtoul (temp_ptr + 8, NULL, 10);
111 latest_entry_time = temp_entry_time;
112 break;
113 } else if ((temp_ptr = strtok (input_buffer, "]")) != NULL) {
114 temp_entry_time = strtoul (temp_ptr + 1, NULL, 10);
115 if (temp_entry_time > latest_entry_time)
116 latest_entry_time = temp_entry_time;
119 fclose (fp);
121 if (verbose >= 2)
122 printf("command: %s\n", PS_COMMAND);
124 /* run the command to check for the Nagios process.. */
125 if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0)
126 result = STATE_WARNING;
128 /* count the number of matching Nagios processes... */
129 for(i = 0; i < chld_out.lines; i++) {
130 cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST);
131 /* Zombie processes do not give a procprog command */
132 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
133 cols = expected_cols;
134 /* Set some value for procargs for the strip command further below
135 * Seen to be a problem on some Solaris 7 and 8 systems */
136 chld_out.line[i][pos] = '\n';
137 chld_out.line[i][pos+1] = 0x0;
139 if ( cols >= expected_cols ) {
140 xasprintf (&procargs, "%s", chld_out.line[i] + pos);
141 strip (procargs);
143 /* Some ps return full pathname for command. This removes path */
144 temp_string = strtok ((char *)procprog, "/");
145 while (temp_string) {
146 strcpy(procprog, temp_string);
147 temp_string = strtok (NULL, "/");
150 /* May get empty procargs */
151 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) {
152 proc_entries++;
153 if (verbose >= 2) {
154 printf (_("Found process: %s %s\n"), procprog, procargs);
160 /* If we get anything on stderr, at least set warning */
161 if(chld_err.buflen)
162 result = max_state (result, STATE_WARNING);
164 /* reset the alarm handler */
165 alarm (0);
167 if (proc_entries == 0) {
168 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!"));
171 if (latest_entry_time == 0L) {
172 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
175 time (&current_time);
176 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
177 result = STATE_WARNING;
178 } else {
179 result = STATE_OK;
182 printf ("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING"));
183 printf (ngettext ("%d process", "%d processes", proc_entries), proc_entries);
184 printf (", ");
185 printf (
186 ngettext ("status log updated %d second ago",
187 "status log updated %d seconds ago",
188 (int) (current_time - latest_entry_time) ),
189 (int) (current_time - latest_entry_time) );
190 printf ("\n");
192 return result;
197 /* process command-line arguments */
199 process_arguments (int argc, char **argv)
201 int c;
203 int option = 0;
204 static struct option longopts[] = {
205 {"filename", required_argument, 0, 'F'},
206 {"expires", required_argument, 0, 'e'},
207 {"command", required_argument, 0, 'C'},
208 {"timeout", optional_argument, 0, 't'},
209 {"version", no_argument, 0, 'V'},
210 {"help", no_argument, 0, 'h'},
211 {"verbose", no_argument, 0, 'v'},
212 {0, 0, 0, 0}
215 if (argc < 2)
216 return ERROR;
218 if (!is_option (argv[1])) {
219 status_log = argv[1];
220 if (is_intnonneg (argv[2]))
221 expire_minutes = atoi (argv[2]);
222 else
223 die (STATE_UNKNOWN,
224 _("Expiration time must be an integer (seconds)\n"));
225 process_string = argv[3];
226 return OK;
229 while (1) {
230 c = getopt_long (argc, argv, "+hVvF:C:e:t:", longopts, &option);
232 if (c == -1 || c == EOF || c == 1)
233 break;
235 switch (c) {
236 case 'h': /* help */
237 print_help ();
238 exit (STATE_UNKNOWN);
239 case 'V': /* version */
240 print_revision (progname, NP_VERSION);
241 exit (STATE_UNKNOWN);
242 case 'F': /* status log */
243 status_log = optarg;
244 break;
245 case 'C': /* command */
246 process_string = optarg;
247 break;
248 case 'e': /* expiry time */
249 if (is_intnonneg (optarg))
250 expire_minutes = atoi (optarg);
251 else
252 die (STATE_UNKNOWN,
253 _("Expiration time must be an integer (seconds)\n"));
254 break;
255 case 't': /* timeout */
256 if (is_intnonneg (optarg))
257 timeout_interval = atoi (optarg);
258 else
259 die (STATE_UNKNOWN,
260 _("Timeout must be an integer (seconds)\n"));
261 break;
262 case 'v':
263 verbose++;
264 break;
265 default: /* print short usage_va statement if args not parsable */
266 usage5();
271 if (status_log == NULL)
272 die (STATE_UNKNOWN, _("You must provide the status_log\n"));
274 if (process_string == NULL)
275 die (STATE_UNKNOWN, _("You must provide a process string\n"));
277 return OK;
282 void
283 print_help (void)
285 print_revision (progname, NP_VERSION);
287 printf (_(COPYRIGHT), copyright, email);
289 printf ("%s\n", _("This plugin checks the status of the Nagios process on the local machine"));
290 printf ("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
291 printf ("%s\n", _("the number of minutes specified by the expires option."));
292 printf ("%s\n", _("It also checks the process table for a process matching the command argument."));
294 printf ("\n\n");
296 print_usage ();
298 printf (UT_HELP_VRSN);
299 printf (UT_EXTRA_OPTS);
301 printf (" %s\n", "-F, --filename=FILE");
302 printf (" %s\n", _("Name of the log file to check"));
303 printf (" %s\n", "-e, --expires=INTEGER");
304 printf (" %s\n", _("Minutes aging after which logfile is considered stale"));
305 printf (" %s\n", "-C, --command=STRING");
306 printf (" %s\n", _("Substring to search for in process arguments"));
307 printf (" %s\n", "-t, --timeout=INTEGER");
308 printf (" %s\n", _("Timeout for the plugin in seconds"));
309 printf (UT_VERBOSE);
311 printf ("\n");
312 printf ("%s\n", _("Examples:"));
313 printf (" %s\n", "check_nagios -t 20 -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
315 printf (UT_SUPPORT);
320 void
321 print_usage (void)
323 printf ("%s\n", _("Usage:"));
324 printf ("%s -F <status log file> -t <timeout_seconds> -e <expire_minutes> -C <process_string>\n", progname);