Code

c7be780f95d2a2e74a2ea154baf5fd29caef7d5a
[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-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 (&current_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;
181 /* process command-line arguments */
182 int
183 process_arguments (int argc, char **argv)
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;
258 void
259 print_help (void)
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");
271   
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));
291 void
292 print_usage (void)
294   printf (_("Usage:"));
295         printf ("%s -F <status log file> -e <expire_minutes> -C <process_string>\n", progname);