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_load";
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 "utils.h"
28 #include "popen.h"
30 #ifdef HAVE_SYS_LOADAVG_H
31 #include <sys/loadavg.h>
32 #endif
34 /* needed for compilation under NetBSD, as suggested by Andy Doran */
35 #ifndef LOADAVG_1MIN
36 #define LOADAVG_1MIN 0
37 #define LOADAVG_5MIN 1
38 #define LOADAVG_15MIN 2
39 #endif /* !defined LOADAVG_1MIN */
42 int process_arguments (int argc, char **argv);
43 int validate_arguments (void);
44 void print_help (void);
45 void print_usage (void);
47 float wload1 = -1, wload5 = -1, wload15 = -1;
48 float cload1 = -1, cload5 = -1, cload15 = -1;
50 char *status_line;
56 \f
57 int
58 main (int argc, char **argv)
59 {
60 int result;
61 #if HAVE_GETLOADAVG==1
62 double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */
63 #else
64 # if HAVE_PROC_LOADAVG==1
65 FILE *fp;
66 char input_buffer[MAX_INPUT_BUFFER];
67 char *tmp_ptr;
68 # else
69 char input_buffer[MAX_INPUT_BUFFER];
70 # endif
71 #endif
73 float la1, la5, la15;
75 setlocale (LC_ALL, "");
76 bindtextdomain (PACKAGE, LOCALEDIR);
77 textdomain (PACKAGE);
79 if (process_arguments (argc, argv) == ERROR)
80 usage (_("check_load: could not parse arguments\n"));
82 #if HAVE_GETLOADAVG==1
83 result = getloadavg (la, 3);
84 if (result == -1)
85 return STATE_UNKNOWN;
86 la1 = la[LOADAVG_1MIN];
87 la5 = la[LOADAVG_5MIN];
88 la15 = la[LOADAVG_15MIN];
89 #else
90 # if HAVE_PROC_LOADAVG==1
91 fp = fopen (PROC_LOADAVG, "r");
92 if (fp == NULL) {
93 printf (_("Error opening %s\n"), PROC_LOADAVG);
94 return STATE_UNKNOWN;
95 }
97 la1 = la5 = la15 = -1;
99 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
100 tmp_ptr = strtok (input_buffer, " ");
101 la1 = atof (tmp_ptr);
102 tmp_ptr = strtok (NULL, " ");
103 la5 = atof (tmp_ptr);
104 tmp_ptr = strtok (NULL, " ");
105 la15 = atof (tmp_ptr);
106 }
108 fclose (fp);
109 # else
110 child_process = spopen (PATH_TO_UPTIME);
111 if (child_process == NULL) {
112 printf (_("Error opening %s\n"), PATH_TO_UPTIME);
113 return STATE_UNKNOWN;
114 }
115 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
116 if (child_stderr == NULL) {
117 printf (_("Could not open stderr for %s\n"), PATH_TO_UPTIME);
118 }
119 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
120 sscanf (input_buffer, "%*[^l]load average: %f, %f, %f", &la1, &la5, &la15);
122 result = spclose (child_process);
123 if (result) {
124 printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME);
125 return STATE_UNKNOWN;
126 }
127 # endif
128 #endif
131 if ((la1 < 0.0) || (la5 < 0.0) || (la15 < 0.0)) {
132 #if HAVE_GETLOADAVG==1
133 printf (_("Error in getloadavg()\n"));
134 #else
135 # if HAVE_PROC_LOADAVG==1
136 printf (_("Error processing %s\n"), PROC_LOADAVG);
137 # else
138 printf (_("Error processing %s\n"), PATH_TO_UPTIME);
139 # endif
140 #endif
141 return STATE_UNKNOWN;
142 }
144 asprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15);
146 if ((la1 >= cload1) || (la5 >= cload5) || (la15 >= cload15))
147 result = STATE_CRITICAL;
148 else if ((la1 >= wload1) || (la5 >= wload5) || (la15 >= wload15))
149 result = STATE_WARNING;
150 else
151 result = STATE_OK;
153 die (result,
154 "%s - %s|%s %s %s\n",
155 state_text (result),
156 status_line,
157 fperfdata ("load1", la1, "", (int)wload1, wload1, (int)cload1, cload1, TRUE, 0, FALSE, 0),
158 fperfdata ("load5", la5, "", (int)wload5, wload5, (int)cload5, cload5, TRUE, 0, FALSE, 0),
159 fperfdata ("load15", la15, "", (int)wload15, wload15, (int)cload15, cload15, TRUE, 0, FALSE, 0));
160 return STATE_OK;
161 }
167 \f
168 /* process command-line arguments */
169 int
170 process_arguments (int argc, char **argv)
171 {
172 int c = 0;
174 int option = 0;
175 static struct option longopts[] = {
176 {"warning", required_argument, 0, 'w'},
177 {"critical", required_argument, 0, 'c'},
178 {"version", no_argument, 0, 'V'},
179 {"help", no_argument, 0, 'h'},
180 {0, 0, 0, 0}
181 };
183 if (argc < 2)
184 return ERROR;
186 while (1) {
187 c = getopt_long (argc, argv, "Vhc:w:", longopts, &option);
189 if (c == -1 || c == EOF)
190 break;
192 switch (c) {
193 case 'w': /* warning time threshold */
194 if (is_intnonneg (optarg)) {
195 wload1 = atof (optarg);
196 wload5 = atof (optarg);
197 wload15 = atof (optarg);
198 break;
199 }
200 else if (strstr (optarg, ",") &&
201 sscanf (optarg, "%f,%f,%f", &wload1, &wload5, &wload15) == 3)
202 break;
203 else if (strstr (optarg, ":") &&
204 sscanf (optarg, "%f:%f:%f", &wload1, &wload5, &wload15) == 3)
205 break;
206 else
207 usage (_("Warning threshold must be float or float triplet!\n"));
208 break;
209 case 'c': /* critical time threshold */
210 if (is_intnonneg (optarg)) {
211 cload1 = atof (optarg);
212 cload5 = atof (optarg);
213 cload15 = atof (optarg);
214 break;
215 }
216 else if (strstr (optarg, ",") &&
217 sscanf (optarg, "%f,%f,%f", &cload1, &cload5, &cload15) == 3)
218 break;
219 else if (strstr (optarg, ":") &&
220 sscanf (optarg, "%f:%f:%f", &cload1, &cload5, &cload15) == 3)
221 break;
222 else
223 usage (_("Critical threshold must be float or float triplet!\n"));
224 break;
225 case 'V': /* version */
226 print_revision (progname, "$Revision$");
227 exit (STATE_OK);
228 case 'h': /* help */
229 print_help ();
230 exit (STATE_OK);
231 case '?': /* help */
232 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
233 print_usage ();
234 exit (STATE_UNKNOWN);
235 }
236 }
238 c = optind;
239 if (c == argc)
240 return validate_arguments ();
241 if (wload1 < 0 && is_nonnegative (argv[c]))
242 wload1 = atof (argv[c++]);
244 if (c == argc)
245 return validate_arguments ();
246 if (cload1 < 0 && is_nonnegative (argv[c]))
247 cload1 = atof (argv[c++]);
249 if (c == argc)
250 return validate_arguments ();
251 if (wload5 < 0 && is_nonnegative (argv[c]))
252 wload5 = atof (argv[c++]);
254 if (c == argc)
255 return validate_arguments ();
256 if (cload5 < 0 && is_nonnegative (argv[c]))
257 cload5 = atof (argv[c++]);
259 if (c == argc)
260 return validate_arguments ();
261 if (wload15 < 0 && is_nonnegative (argv[c]))
262 wload15 = atof (argv[c++]);
264 if (c == argc)
265 return validate_arguments ();
266 if (cload15 < 0 && is_nonnegative (argv[c]))
267 cload15 = atof (argv[c++]);
269 return validate_arguments ();
270 }
276 int
277 validate_arguments (void)
278 {
279 if (wload1 < 0)
280 usage (_("Warning threshold for 1-minute load average is not specified\n"));
281 if (wload5 < 0)
282 usage (_("Warning threshold for 5-minute load average is not specified\n"));
283 if (wload15 < 0)
284 usage (_("Warning threshold for 15-minute load average is not specified\n"));
285 if (cload1 < 0)
286 usage (_("Critical threshold for 1-minute load average is not specified\n"));
287 if (cload5 < 0)
288 usage (_("Critical threshold for 5-minute load average is not specified\n"));
289 if (cload15 < 0)
290 usage (_("Critical threshold for 15-minute load average is not specified\n"));
291 if (wload1 > cload1)
292 usage (_("Parameter inconsistency: 1-minute \"warning load\" greater than \"critical load\".\n"));
293 if (wload5 > cload5)
294 usage (_("Parameter inconsistency: 5-minute \"warning load\" greater than \"critical load\".\n"));
295 if (wload15 > cload15)
296 usage (_("Parameter inconsistency: 15-minute \"warning load\" greater than \"critical load\".\n"));
297 return OK;
298 }
304 \f
305 void
306 print_help (void)
307 {
308 print_revision (progname, revision);
310 printf ("Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>\n");
311 printf (COPYRIGHT, copyright, email);
313 printf (_("This plugin tests the current system load average.\n\n"));
315 print_usage ();
317 printf (_(UT_HELP_VRSN));
319 printf (_("\
320 -w, --warning=WLOAD1,WLOAD5,WLOAD15\n\
321 Exit with WARNING status if load average exceeds WLOADn\n\
322 -c, --critical=CLOAD1,CLOAD5,CLOAD15\n\
323 Exit with CRITICAL status if load average exceed CLOADn\n\n\
324 the load average format is the same used by \"uptime\" and \"w\"\n\n"));
326 printf (_(UT_SUPPORT));
327 }
329 void
330 print_usage (void)
331 {
332 printf (_("Usage: %s -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n"),
333 progname);
334 printf (_(UT_HLP_VRS), progname, progname);
335 }