Code

618ee57313a086938ea3b1f4d021ba9584ca2def
[nagiosplug.git] / plugins / check_nagios.c
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$
18  
19 ******************************************************************************/
21 const char *progname = "check_nagios";
22 const char *revision = "$Revision$";
23 const char *copyright = "1999-2003";
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);
127                         
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 (&current_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;
182 /* process command-line arguments */
183 int
184 process_arguments (int argc, char **argv)
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;
266 void
267 print_help (void)
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"));
301 void
302 print_usage (void)
304         printf (_("\
305 Usage: %s -F <status log file> -e <expire_minutes> -C <process_string>\n"),
306                 progname);