Git commit notifications via post-receive hook
[monitoring-plugins.git] / plugins / check_nagios.c
blob954ff711707dfc4402283d1cd7a197fe51af66e1
1 /*****************************************************************************
2 *
3 * Nagios check_nagios plugin
4 *
5 * License: GPL
6 * Copyright (c) 1999-2007 Nagios 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 = "nagiosplug-devel@lists.sourceforge.net";
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 asprintf (&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 {"version", no_argument, 0, 'V'},
209 {"help", no_argument, 0, 'h'},
210 {"verbose", no_argument, 0, 'v'},
211 {0, 0, 0, 0}
214 if (argc < 2)
215 return ERROR;
217 if (!is_option (argv[1])) {
218 status_log = argv[1];
219 if (is_intnonneg (argv[2]))
220 expire_minutes = atoi (argv[2]);
221 else
222 die (STATE_UNKNOWN,
223 _("Expiration time must be an integer (seconds)\n"));
224 process_string = argv[3];
225 return OK;
228 while (1) {
229 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
231 if (c == -1 || c == EOF || c == 1)
232 break;
234 switch (c) {
235 case 'h': /* help */
236 print_help ();
237 exit (STATE_OK);
238 case 'V': /* version */
239 print_revision (progname, NP_VERSION);
240 exit (STATE_OK);
241 case 'F': /* status log */
242 status_log = optarg;
243 break;
244 case 'C': /* command */
245 process_string = optarg;
246 break;
247 case 'e': /* expiry time */
248 if (is_intnonneg (optarg))
249 expire_minutes = atoi (optarg);
250 else
251 die (STATE_UNKNOWN,
252 _("Expiration time must be an integer (seconds)\n"));
253 break;
254 case 'v':
255 verbose++;
256 break;
257 default: /* print short usage_va statement if args not parsable */
258 usage5();
263 if (status_log == NULL)
264 die (STATE_UNKNOWN, _("You must provide the status_log\n"));
266 if (process_string == NULL)
267 die (STATE_UNKNOWN, _("You must provide a process string\n"));
269 return OK;
274 void
275 print_help (void)
277 print_revision (progname, NP_VERSION);
279 printf (_(COPYRIGHT), copyright, email);
281 printf ("%s\n", _("This plugin checks the status of the Nagios process on the local machine"));
282 printf ("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
283 printf ("%s\n", _("the number of minutes specified by the expires option."));
284 printf ("%s\n", _("It also checks the process table for a process matching the command argument."));
286 printf ("\n\n");
288 print_usage ();
290 printf (_(UT_HELP_VRSN));
291 printf (_(UT_EXTRA_OPTS));
293 printf (" %s\n", "-F, --filename=FILE");
294 printf (" %s\n", _("Name of the log file to check"));
295 printf (" %s\n", "-e, --expires=INTEGER");
296 printf (" %s\n", _("Minutes aging after which logfile is considered stale"));
297 printf (" %s\n", "-C, --command=STRING");
298 printf (" %s\n", _("Substring to search for in process arguments"));
299 printf (_(UT_VERBOSE));
301 #ifdef NP_EXTRA_OPTS
302 printf ("\n");
303 printf ("%s\n", _("Notes:"));
304 printf (_(UT_EXTRA_OPTS_NOTES));
305 #endif
307 printf ("\n");
308 printf ("%s\n", _("Examples:"));
309 printf (" %s\n", "check_nagios -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
311 printf (_(UT_SUPPORT));
316 void
317 print_usage (void)
319 printf (_("Usage:"));
320 printf ("%s -F <status log file> -e <expire_minutes> -C <process_string>\n", progname);