1 /******************************************************************************
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2 of the License, or
6 (at your option) any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 ******************************************************************************/
19 const char *progname = "check_nagios";
20 const char *revision = "$Revision$";
21 const char *copyright = "1999-2003";
22 const char *email = "nagiosplug-devel@lists.sourceforge.net";
24 #include "common.h"
25 #include "popen.h"
26 #include "utils.h"
28 void
29 print_usage (void)
30 {
31 printf (_("\
32 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
33 progname);
34 }
36 void
37 print_help (void)
38 {
39 print_revision (progname, revision);
41 printf (_(COPYRIGHT), copyright, email);
43 printf (_("\
44 This plugin attempts to check the status of the Nagios process on the local\n\
45 machine. The plugin will check to make sure the Nagios status log is no older\n\
46 than the number of minutes specified by the <expire_minutes> option. It also\n\
47 uses the /bin/ps command to check for a process matching whatever you specify\n\
48 by the <process_string> argument.\n"));
50 print_usage ();
52 printf (_(UT_HELP_VRSN));
54 printf (_("\
55 -F, --filename=FILE\n\
56 Name of the log file to check\n\
57 -e, --expires=INTEGER\n\
58 Seconds aging afterwhich logfile is condsidered stale\n\
59 -C, --command=STRING\n\
60 Command to search for in process table\n"));
62 printf (_("\
63 Example:\n\
64 ./check_nagios -e 5 \\\
65 -F /usr/local/nagios/var/status.log \\\
66 -C /usr/local/nagios/bin/nagios\n"));
67 }
68 \f
69 int process_arguments (int, char **);
71 char *status_log = NULL;
72 char *process_string = NULL;
73 int expire_minutes = 0;
75 int verbose = 0;
77 int
78 main (int argc, char **argv)
79 {
80 int result = STATE_UNKNOWN;
81 char input_buffer[MAX_INPUT_BUFFER];
82 unsigned long latest_entry_time = 0L;
83 unsigned long temp_entry_time = 0L;
84 int proc_entries = 0;
85 time_t current_time;
86 char *temp_ptr;
87 FILE *fp;
88 int procuid = 0;
89 int procppid = 0;
90 int procvsz = 0;
91 int procrss = 0;
92 float procpcpu = 0;
93 char procstat[8];
94 char procprog[MAX_INPUT_BUFFER];
95 char *procargs;
96 int pos, cols;
98 if (process_arguments (argc, argv) == ERROR)
99 usage (_("Could not parse arguments\n"));
101 /* Set signal handling and alarm */
102 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
103 printf (_("Cannot catch SIGALRM"));
104 return STATE_UNKNOWN;
105 }
107 /* handle timeouts gracefully... */
108 alarm (timeout_interval);
110 /* open the status log */
111 fp = fopen (status_log, "r");
112 if (fp == NULL) {
113 printf (_("Error: Cannot open status log for reading!\n"));
114 return STATE_CRITICAL;
115 }
117 /* get the date/time of the last item updated in the log */
118 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
119 temp_ptr = strtok (input_buffer, "]");
120 temp_entry_time =
121 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
122 if (temp_entry_time > latest_entry_time)
123 latest_entry_time = temp_entry_time;
124 }
125 fclose (fp);
127 /* run the command to check for the Nagios process.. */
128 child_process = spopen (PS_COMMAND);
129 if (child_process == NULL) {
130 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
131 return STATE_UNKNOWN;
132 }
134 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
135 if (child_stderr == NULL) {
136 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
137 }
139 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
141 /* count the number of matching Nagios processes... */
142 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
143 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
144 if ( cols >= 6 ) {
145 asprintf (&procargs, "%s", input_buffer + pos);
146 strip (procargs);
148 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string)) {
149 proc_entries++;
150 if (verbose)
151 printf (_("Found process: %s\n"), procargs);
152 }
153 }
154 }
156 /* If we get anything on stderr, at least set warning */
157 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
158 result = max_state (result, STATE_WARNING);
160 /* close stderr */
161 (void) fclose (child_stderr);
163 /* close the pipe */
164 if (spclose (child_process))
165 result = max_state (result, STATE_WARNING);
167 /* reset the alarm handler */
168 alarm (0);
170 if (proc_entries == 0) {
171 printf (_("Could not locate a running Nagios process!\n"));
172 return STATE_CRITICAL;
173 }
175 result = STATE_OK;
177 time (¤t_time);
178 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
179 result = STATE_WARNING;
181 printf
182 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
183 (result == STATE_OK) ? "ok" : "problem", proc_entries,
184 (proc_entries == 1) ? "" : "es",
185 (int) (current_time - latest_entry_time),
186 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
188 return result;
189 }
195 /* process command-line arguments */
196 int
197 process_arguments (int argc, char **argv)
198 {
199 int c;
201 int option_index = 0;
202 static struct option long_options[] = {
203 {"filename", required_argument, 0, 'F'},
204 {"expires", required_argument, 0, 'e'},
205 {"command", required_argument, 0, 'C'},
206 {"version", no_argument, 0, 'V'},
207 {"help", no_argument, 0, 'h'},
208 {"verbose", no_argument, 0, 'v'},
209 {0, 0, 0, 0}
210 };
212 if (argc < 2)
213 return ERROR;
215 if (!is_option (argv[1])) {
216 status_log = argv[1];
217 if (is_intnonneg (argv[2]))
218 expire_minutes = atoi (argv[2]);
219 else
220 terminate (STATE_UNKNOWN,
221 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
222 progname);
223 process_string = argv[3];
224 return OK;
225 }
227 while (1) {
228 c = getopt_long (argc, argv, "+hVvF:C:e:", long_options, &option_index);
230 if (c == -1 || c == EOF || c == 1)
231 break;
233 switch (c) {
234 case '?': /* print short usage statement if args not parsable */
235 printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
236 print_usage ();
237 exit (STATE_UNKNOWN);
238 case 'h': /* help */
239 print_help ();
240 exit (STATE_OK);
241 case 'V': /* version */
242 print_revision (progname, "$Revision$");
243 exit (STATE_OK);
244 case 'F': /* status log */
245 status_log = optarg;
246 break;
247 case 'C': /* command */
248 process_string = optarg;
249 break;
250 case 'e': /* expiry time */
251 if (is_intnonneg (optarg))
252 expire_minutes = atoi (optarg);
253 else
254 terminate (STATE_UNKNOWN,
255 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
256 progname);
257 break;
258 case 'v':
259 verbose++;
260 break;
261 }
262 }
265 if (status_log == NULL)
266 terminate (STATE_UNKNOWN,
267 _("You must provide the status_log\nType '%s -h' for additional help\n"),
268 progname);
269 else if (process_string == NULL)
270 terminate (STATE_UNKNOWN,
271 _("You must provide a process string\nType '%s -h' for additional help\n"),
272 progname);
274 return OK;
275 }