694c069c5cfdd895835a74ac9d435f1665c14c00
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 procetime[MAX_INPUT_BUFFER];
58 char procprog[MAX_INPUT_BUFFER];
59 char *procargs;
60 int pos, cols;
61 int expected_cols = PS_COLS - 1;
62 const char *zombie = "Z";
63 char *temp_string;
65 setlocale (LC_ALL, "");
66 bindtextdomain (PACKAGE, LOCALEDIR);
67 textdomain (PACKAGE);
69 if (process_arguments (argc, argv) != TRUE)
70 usage4 (_("Could not parse arguments"));
72 /* Set signal handling and alarm timeout */
73 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
74 usage4 (_("Cannot catch SIGALRM"));
75 }
77 /* handle timeouts gracefully... */
78 alarm (timeout_interval);
80 /* open the status log */
81 fp = fopen (status_log, "r");
82 if (fp == NULL) {
83 printf (_("CRITICAL - Cannot open status log for reading!\n"));
84 return STATE_CRITICAL;
85 }
87 /* get the date/time of the last item updated in the log */
88 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
89 temp_ptr = strtok (input_buffer, "]");
90 temp_entry_time =
91 (temp_ptr == NULL) ? 0L : strtoul (temp_ptr + 1, NULL, 10);
92 if (temp_entry_time > latest_entry_time)
93 latest_entry_time = temp_entry_time;
94 }
95 fclose (fp);
97 if (verbose >= 2)
98 printf("command: %s\n", PS_COMMAND);
100 /* run the command to check for the Nagios process.. */
101 child_process = spopen (PS_COMMAND);
102 if (child_process == NULL) {
103 printf (_("Could not open pipe: %s\n"), PS_COMMAND);
104 return STATE_UNKNOWN;
105 }
107 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
108 if (child_stderr == NULL) {
109 printf (_("Could not open stderr for %s\n"), PS_COMMAND);
110 }
112 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
114 /* count the number of matching Nagios processes... */
115 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process)) {
116 cols = sscanf (input_buffer, PS_FORMAT, PS_VARLIST);
117 /* Zombie processes do not give a procprog command */
118 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
119 cols = expected_cols;
120 /* Set some value for procargs for the strip command further below
121 Seen to be a problem on some Solaris 7 and 8 systems */
122 input_buffer[pos] = '\n';
123 input_buffer[pos+1] = 0x0;
124 }
125 if ( cols >= expected_cols ) {
126 asprintf (&procargs, "%s", input_buffer + pos);
127 strip (procargs);
129 /* Some ps return full pathname for command. This removes path */
130 temp_string = strtok ((char *)procprog, "/");
131 while (temp_string) {
132 strcpy(procprog, temp_string);
133 temp_string = strtok (NULL, "/");
134 }
136 /* May get empty procargs */
137 if (!strstr(procargs, argv[0]) && strstr(procprog, process_string) && strcmp(procargs,"")) {
138 proc_entries++;
139 if (verbose >= 2) {
140 printf (_("Found process: %s %s\n"), procprog, procargs);
141 }
142 }
143 }
144 }
146 /* If we get anything on stderr, at least set warning */
147 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_stderr))
148 result = max_state (result, STATE_WARNING);
150 /* close stderr */
151 (void) fclose (child_stderr);
153 /* close the pipe */
154 if (spclose (child_process))
155 result = max_state (result, STATE_WARNING);
157 /* reset the alarm handler */
158 alarm (0);
160 if (proc_entries == 0) {
161 printf (_("Could not locate a running Nagios process!\n"));
162 return STATE_CRITICAL;
163 }
165 result = STATE_OK;
167 time (¤t_time);
168 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60))
169 result = STATE_WARNING;
171 printf
172 (_("Nagios %s: located %d process%s, status log updated %d second%s ago\n"),
173 (result == STATE_OK) ? "ok" : "problem", proc_entries,
174 (proc_entries == 1) ? "" : "es",
175 (int) (current_time - latest_entry_time),
176 ((int) (current_time - latest_entry_time) == 1) ? "" : "s");
178 return result;
179 }
183 /* process command-line arguments */
184 int
185 process_arguments (int argc, char **argv)
186 {
187 int c;
189 int option = 0;
190 static struct option longopts[] = {
191 {"filename", required_argument, 0, 'F'},
192 {"expires", required_argument, 0, 'e'},
193 {"command", required_argument, 0, 'C'},
194 {"version", no_argument, 0, 'V'},
195 {"help", no_argument, 0, 'h'},
196 {"verbose", no_argument, 0, 'v'},
197 {0, 0, 0, 0}
198 };
200 if (argc < 2)
201 return ERROR;
203 if (!is_option (argv[1])) {
204 status_log = argv[1];
205 if (is_intnonneg (argv[2]))
206 expire_minutes = atoi (argv[2]);
207 else
208 die (STATE_UNKNOWN,
209 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
210 progname);
211 process_string = argv[3];
212 return OK;
213 }
215 while (1) {
216 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
218 if (c == -1 || c == EOF || c == 1)
219 break;
221 switch (c) {
222 case '?': /* print short usage statement if args not parsable */
223 printf (_("%s: Unknown argument: %c\n\n"), progname, optopt);
224 print_usage ();
225 exit (STATE_UNKNOWN);
226 case 'h': /* help */
227 print_help ();
228 exit (STATE_OK);
229 case 'V': /* version */
230 print_revision (progname, revision);
231 exit (STATE_OK);
232 case 'F': /* status log */
233 status_log = optarg;
234 break;
235 case 'C': /* command */
236 process_string = optarg;
237 break;
238 case 'e': /* expiry time */
239 if (is_intnonneg (optarg))
240 expire_minutes = atoi (optarg);
241 else
242 die (STATE_UNKNOWN,
243 _("Expiration time must be an integer (seconds)\nType '%s -h' for additional help\n"),
244 progname);
245 break;
246 case 'v':
247 verbose++;
248 break;
249 }
250 }
253 if (status_log == NULL)
254 die (STATE_UNKNOWN,
255 _("You must provide the status_log\nType '%s -h' for additional help\n"),
256 progname);
257 else if (process_string == NULL)
258 die (STATE_UNKNOWN,
259 _("You must provide a process string\nType '%s -h' for additional help\n"),
260 progname);
262 return OK;
263 }
267 void
268 print_help (void)
269 {
270 print_revision (progname, revision);
272 printf (_(COPYRIGHT), copyright, email);
274 printf (_("\
275 This plugin attempts to check the status of the Nagios process on the local\n\
276 machine. The plugin will check to make sure the Nagios status log is no older\n\
277 than the number of minutes specified by the <expire_minutes> option. It also\n\
278 uses the /bin/ps command to check for a process matching whatever you specify\n\
279 by the <process_string> argument.\n"));
281 print_usage ();
283 printf (_(UT_HELP_VRSN));
285 printf (_("\
286 -F, --filename=FILE\n\
287 Name of the log file to check\n\
288 -e, --expires=INTEGER\n\
289 Seconds aging afterwhich logfile is condsidered stale\n\
290 -C, --command=STRING\n\
291 Command to search for in process table\n"));
293 printf (_("\
294 Example:\n\
295 ./check_nagios -e 5 \\\
296 -F /usr/local/nagios/var/status.log \\\
297 -C /usr/local/nagios/bin/nagios\n"));
298 }
302 void
303 print_usage (void)
304 {
305 printf ("\
306 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n",
307 progname);
309 printf (UT_HLP_VRS, progname, progname);
310 }