1daf5401286b45f19d1f0139280272d8f2941995
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 $Id$
19 ******************************************************************************/
21 const char *progname = "check_nagios";
22 const char *revision = "$Revision$";
23 const char *copyright = "1999-2004";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "popen.h"
28 #include "utils.h"
30 int process_arguments (int, char **);
31 void print_help (void);
32 void print_usage (void);
34 char *status_log = NULL;
35 char *process_string = NULL;
36 int expire_minutes = 0;
38 int verbose = 0;
40 int
41 main (int argc, char **argv)
42 {
43 int result = STATE_UNKNOWN;
44 char input_buffer[MAX_INPUT_BUFFER];
45 unsigned long latest_entry_time = 0L;
46 unsigned long temp_entry_time = 0L;
47 int proc_entries = 0;
48 time_t current_time;
49 char *temp_ptr;
50 FILE *fp;
51 int procuid = 0;
52 int procppid = 0;
53 int procvsz = 0;
54 int procrss = 0;
55 float procpcpu = 0;
56 char procstat[8];
57 char procprog[MAX_INPUT_BUFFER];
58 char *procargs;
59 int pos, cols;
60 int expected_cols = PS_COLS - 1;
61 const char *zombie = "Z";
62 char *temp_string;
64 setlocale (LC_ALL, "");
65 bindtextdomain (PACKAGE, LOCALEDIR);
66 textdomain (PACKAGE);
68 if (process_arguments (argc, argv) != TRUE)
69 usage4 (_("Could not parse arguments"));
71 /* Set signal handling and alarm timeout */
72 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
73 usage4 (_("Cannot catch SIGALRM"));
74 }
76 /* handle timeouts gracefully... */
77 alarm (timeout_interval);
79 /* open the status log */
80 fp = fopen (status_log, "r");
81 if (fp == NULL) {
82 printf (_("CRITICAL - Cannot open status log for reading!\n"));
83 return STATE_CRITICAL;
84 }
86 /* get the date/time of the last item updated in the log */
87 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
88 temp_ptr = strtok (input_buffer, "]");
89 temp_entry_time =
90 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
91 if (temp_entry_time > latest_entry_time)
92 latest_entry_time = temp_entry_time;
93 }
94 fclose (fp);
96 if (verbose >= 2)
97 printf("command: %s\n", PS_COMMAND);
99 /* run the command to check for the Nagios process.. */
100 child_process = spopen (PS_COMMAND);
101 if (child_process == NULL) {
102 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
103 return STATE_UNKNOWN;
104 }
106 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
107 if (child_stderr == NULL) {
108 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
109 }
111 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
113 /* count the number of matching Nagios processes... */
114 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
115 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
116 /* Zombie processes do not give a procprog command */
117 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
118 cols = expected_cols;
119 /* Set some value for procargs for the strip command further below
120 Seen to be a problem on some Solaris 7 and 8 systems */
121 input_buffer[pos] = '\n';
122 input_buffer[pos+1] = 0x0;
123 }
124 if ( cols >= expected_cols ) {
125 asprintf (&procargs, "%s", input_buffer + pos);
126 strip (procargs);
128 /* Some ps return full pathname for command. This removes path */
129 temp_string = strtok ((char *)procprog, "/");
130 while (temp_string) {
131 strcpy(procprog, temp_string);
132 temp_string = strtok (NULL, "/");
133 }
135 /* May get empty procargs */
136 if (!strstr(procargs, argv[0]) && strstr(procprog, process_string) && strcmp(procargs,"")) {
137 proc_entries++;
138 if (verbose >= 2) {
139 printf (_("Found process: %s %s\n"), procprog, procargs);
140 }
141 }
142 }
143 }
145 /* If we get anything on stderr, at least set warning */
146 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
147 result = max_state (result, STATE_WARNING);
149 /* close stderr */
150 (void) fclose (child_stderr);
152 /* close the pipe */
153 if (spclose (child_process))
154 result = max_state (result, STATE_WARNING);
156 /* reset the alarm handler */
157 alarm (0);
159 if (proc_entries == 0) {
160 printf (_("Could not locate a running Nagios process!\n"));
161 return STATE_CRITICAL;
162 }
164 result = STATE_OK;
166 time (¤t_time);
167 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
168 result = STATE_WARNING;
170 printf
171 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
172 (result == STATE_OK) ? "ok" : "problem", proc_entries,
173 (proc_entries == 1) ? "" : "es",
174 (int) (current_time - latest_entry_time),
175 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
177 return result;
178 }
182 /* process command-line arguments */
183 int
184 process_arguments (int argc, char **argv)
185 {
186 int c;
188 int option = 0;
189 static struct option longopts[] = {
190 {"filename", required_argument, 0, 'F'},
191 {"expires", required_argument, 0, 'e'},
192 {"command", required_argument, 0, 'C'},
193 {"version", no_argument, 0, 'V'},
194 {"help", no_argument, 0, 'h'},
195 {"verbose", no_argument, 0, 'v'},
196 {0, 0, 0, 0}
197 };
199 if (argc < 2)
200 return ERROR;
202 if (!is_option (argv[1])) {
203 status_log = argv[1];
204 if (is_intnonneg (argv[2]))
205 expire_minutes = atoi (argv[2]);
206 else
207 die (STATE_UNKNOWN,
208 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
209 progname);
210 process_string = argv[3];
211 return OK;
212 }
214 while (1) {
215 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
217 if (c == -1 || c == EOF || c == 1)
218 break;
220 switch (c) {
221 case '?': /* print short usage statement if args not parsable */
222 printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
223 print_usage ();
224 exit (STATE_UNKNOWN);
225 case 'h': /* help */
226 print_help ();
227 exit (STATE_OK);
228 case 'V': /* version */
229 print_revision (progname, revision);
230 exit (STATE_OK);
231 case 'F': /* status log */
232 status_log = optarg;
233 break;
234 case 'C': /* command */
235 process_string = optarg;
236 break;
237 case 'e': /* expiry time */
238 if (is_intnonneg (optarg))
239 expire_minutes = atoi (optarg);
240 else
241 die (STATE_UNKNOWN,
242 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
243 progname);
244 break;
245 case 'v':
246 verbose++;
247 break;
248 }
249 }
252 if (status_log == NULL)
253 die (STATE_UNKNOWN,
254 _("You must provide the status_log\nType '%s -h' for additional help\n"),
255 progname);
256 else if (process_string == NULL)
257 die (STATE_UNKNOWN,
258 _("You must provide a process string\nType '%s -h' for additional help\n"),
259 progname);
261 return OK;
262 }
266 void
267 print_help (void)
268 {
269 print_revision (progname, revision);
271 printf (_(COPYRIGHT), copyright, email);
273 printf (_("\
274 This plugin attempts to check the status of the Nagios process on the local\n\
275 machine. The plugin will check to make sure the Nagios status log is no older\n\
276 than the number of minutes specified by the <expire_minutes> option. It also\n\
277 uses the /bin/ps command to check for a process matching whatever you specify\n\
278 by the <process_string> argument.\n"));
280 print_usage ();
282 printf (_(UT_HELP_VRSN));
284 printf (_("\
285 -F, --filename=FILE\n\
286 Name of the log file to check\n\
287 -e, --expires=INTEGER\n\
288 Seconds aging afterwhich logfile is condsidered stale\n\
289 -C, --command=STRING\n\
290 Command to search for in process table\n"));
292 printf (_("\
293 Example:\n\
294 ./check_nagios -e 5 \\\
295 -F /usr/local/nagios/var/status.log \\\
296 -C /usr/local/nagios/bin/nagios\n"));
297 }
301 void
302 print_usage (void)
303 {
304 printf (_("\
305 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
306 progname);
307 }