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-2006";
24 const char *email = "nagiosplug-devel@lists.sourceforge.net";
26 #include "common.h"
27 #include "runcmd.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 procpid = 0;
53 int procppid = 0;
54 int procvsz = 0;
55 int procrss = 0;
56 float procpcpu = 0;
57 char procstat[8];
58 #ifdef PS_USES_PROCETIME
59 char procetime[MAX_INPUT_BUFFER];
60 #endif /* PS_USES_PROCETIME */
61 char procprog[MAX_INPUT_BUFFER];
62 char *procargs;
63 int pos, cols;
64 int expected_cols = PS_COLS - 1;
65 const char *zombie = "Z";
66 char *temp_string;
67 output chld_out, chld_err;
68 size_t i;
70 setlocale (LC_ALL, "");
71 bindtextdomain (PACKAGE, LOCALEDIR);
72 textdomain (PACKAGE);
74 if (process_arguments (argc, argv) == ERROR)
75 usage_va(_("Could not parse arguments"));
77 /* Set signal handling and alarm timeout */
78 if (signal (SIGALRM, timeout_alarm_handler) == SIG_ERR) {
79 usage_va(_("Cannot catch SIGALRM"));
80 }
82 /* handle timeouts gracefully... */
83 alarm (timeout_interval);
85 /* open the status log */
86 fp = fopen (status_log, "r");
87 if (fp == NULL) {
88 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot open status log for reading!"));
89 }
91 /* get the date/time of the last item updated in the log */
92 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
93 if ((temp_ptr = strstr (input_buffer, "created=")) != NULL) {
94 temp_entry_time = strtoul (temp_ptr + 8, NULL, 10);
95 latest_entry_time = temp_entry_time;
96 break;
97 } else if ((temp_ptr = strtok (input_buffer, "]")) != NULL) {
98 temp_entry_time = strtoul (temp_ptr + 1, NULL, 10);
99 if (temp_entry_time > latest_entry_time)
100 latest_entry_time = temp_entry_time;
101 }
102 }
103 fclose (fp);
105 if (verbose >= 2)
106 printf("command: %s\n", PS_COMMAND);
108 /* run the command to check for the Nagios process.. */
109 if((result = np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0)) != 0)
110 result = STATE_WARNING;
112 /* count the number of matching Nagios processes... */
113 for(i = 0; i < chld_out.lines; i++) {
114 cols = sscanf (chld_out.line[i], PS_FORMAT, PS_VARLIST);
115 /* Zombie processes do not give a procprog command */
116 if ( cols == (expected_cols - 1) && strstr(procstat, zombie) ) {
117 cols = expected_cols;
118 /* Set some value for procargs for the strip command further below
119 * Seen to be a problem on some Solaris 7 and 8 systems */
120 chld_out.line[i][pos] = '\n';
121 chld_out.line[i][pos+1] = 0x0;
122 }
123 if ( cols >= expected_cols ) {
124 asprintf (&procargs, "%s", chld_out.line[i] + pos);
125 strip (procargs);
127 /* Some ps return full pathname for command. This removes path */
128 temp_string = strtok ((char *)procprog, "/");
129 while (temp_string) {
130 strcpy(procprog, temp_string);
131 temp_string = strtok (NULL, "/");
132 }
134 /* May get empty procargs */
135 if (!strstr(procargs, argv[0]) && strstr(procargs, process_string) && strcmp(procargs,"")) {
136 proc_entries++;
137 if (verbose >= 2) {
138 printf (_("Found process: %s %s\n"), procprog, procargs);
139 }
140 }
141 }
142 }
144 /* If we get anything on stderr, at least set warning */
145 if(chld_err.buflen)
146 result = max_state (result, STATE_WARNING);
148 /* reset the alarm handler */
149 alarm (0);
151 if (proc_entries == 0) {
152 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Could not locate a running Nagios process!"));
153 }
155 if (latest_entry_time == 0L) {
156 die (STATE_CRITICAL, "NAGIOS %s: %s\n", _("CRITICAL"), _("Cannot parse Nagios log file for valid time"));
157 }
159 time (¤t_time);
160 if ((int)(current_time - latest_entry_time) > (expire_minutes * 60)) {
161 result = STATE_WARNING;
162 } else {
163 result = STATE_OK;
164 }
166 printf ("NAGIOS %s: ", (result == STATE_OK) ? _("OK") : _("WARNING"));
167 printf (ngettext ("%d process", "%d processes", proc_entries), proc_entries);
168 printf (", ");
169 printf (
170 ngettext ("status log updated %d second ago",
171 "status log updated %d seconds ago",
172 (int) (current_time - latest_entry_time) ),
173 (int) (current_time - latest_entry_time) );
174 printf ("\n");
176 return result;
177 }
181 /* process command-line arguments */
182 int
183 process_arguments (int argc, char **argv)
184 {
185 int c;
187 int option = 0;
188 static struct option longopts[] = {
189 {"filename", required_argument, 0, 'F'},
190 {"expires", required_argument, 0, 'e'},
191 {"command", required_argument, 0, 'C'},
192 {"version", no_argument, 0, 'V'},
193 {"help", no_argument, 0, 'h'},
194 {"verbose", no_argument, 0, 'v'},
195 {0, 0, 0, 0}
196 };
198 if (argc < 2)
199 return ERROR;
201 if (!is_option (argv[1])) {
202 status_log = argv[1];
203 if (is_intnonneg (argv[2]))
204 expire_minutes = atoi (argv[2]);
205 else
206 die (STATE_UNKNOWN,
207 _("Expiration time must be an integer (seconds)\n"));
208 process_string = argv[3];
209 return OK;
210 }
212 while (1) {
213 c = getopt_long (argc, argv, "+hVvF:C:e:", longopts, &option);
215 if (c == -1 || c == EOF || c == 1)
216 break;
218 switch (c) {
219 case 'h': /* help */
220 print_help ();
221 exit (STATE_OK);
222 case 'V': /* version */
223 print_revision (progname, revision);
224 exit (STATE_OK);
225 case 'F': /* status log */
226 status_log = optarg;
227 break;
228 case 'C': /* command */
229 process_string = optarg;
230 break;
231 case 'e': /* expiry time */
232 if (is_intnonneg (optarg))
233 expire_minutes = atoi (optarg);
234 else
235 die (STATE_UNKNOWN,
236 _("Expiration time must be an integer (seconds)\n"));
237 break;
238 case 'v':
239 verbose++;
240 break;
241 default: /* print short usage_va statement if args not parsable */
242 usage_va(_("Unknown argument - %s"), optarg);
243 }
244 }
247 if (status_log == NULL)
248 die (STATE_UNKNOWN, _("You must provide the status_log\n"));
250 if (process_string == NULL)
251 die (STATE_UNKNOWN, _("You must provide a process string\n"));
253 return OK;
254 }
258 void
259 print_help (void)
260 {
261 print_revision (progname, revision);
263 printf (_(COPYRIGHT), copyright, email);
265 printf ("%s\n", _("This plugin checks the status of the Nagios process on the local machine"));
266 printf ("%s\n", _("The plugin will check to make sure the Nagios status log is no older than"));
267 printf ("%s\n", _("the number of minutes specified by the expires option."));
268 printf ("%s\n", _("It also checks the process table for a process matching the command argument."));
270 printf ("\n\n");
272 print_usage ();
274 printf (_(UT_HELP_VRSN));
276 printf (" %s\n", "-F, --filename=FILE");
277 printf (" %s\n", _("Name of the log file to check"));
278 printf (" %s\n", "-e, --expires=INTEGER");
279 printf (" %s\n", _("Minutes aging after which logfile is considered stale"));
280 printf (" %s\n", "-C, --command=STRING");
281 printf (" %s\n", _("Substring to search for in process arguments"));
282 printf (_(UT_VERBOSE));
283 printf ("\n");
284 printf ("%s\n", _("Examples:"));
285 printf (" %s\n", "check_nagios -e 5 -F /usr/local/nagios/var/status.log -C /usr/local/nagios/bin/nagios");
286 printf (_(UT_SUPPORT));
287 }
291 void
292 print_usage (void)
293 {
294 printf (_("Usage:"));
295 printf ("%s -F <status log file> -e <expire_minutes> -C <process_string>\n", progname);
296 }