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;
54 int
55 main (int argc, char **argv)
56 {
57 int result;
58 #if HAVE_GETLOADAVG==1
59 double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */
60 #else
61 # if HAVE_PROC_LOADAVG==1
62 FILE *fp;
63 char input_buffer[MAX_INPUT_BUFFER];
64 char *tmp_ptr;
65 # else
66 char input_buffer[MAX_INPUT_BUFFER];
67 # endif
68 #endif
70 float la1, la5, la15;
72 setlocale (LC_ALL, "");
73 bindtextdomain (PACKAGE, LOCALEDIR);
74 textdomain (PACKAGE);
76 if (process_arguments (argc, argv) != TRUE)
77 usage (_("check_load: could not parse arguments\n"));
79 #if HAVE_GETLOADAVG==1
80 result = getloadavg (la, 3);
81 if (result == -1)
82 return STATE_UNKNOWN;
83 la1 = la[LOADAVG_1MIN];
84 la5 = la[LOADAVG_5MIN];
85 la15 = la[LOADAVG_15MIN];
86 #else
87 # if HAVE_PROC_LOADAVG==1
88 fp = fopen (PROC_LOADAVG, "r");
89 if (fp == NULL) {
90 printf (_("Error opening %s\n"), PROC_LOADAVG);
91 return STATE_UNKNOWN;
92 }
94 la1 = la5 = la15 = -1;
96 while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) {
97 tmp_ptr = strtok (input_buffer, " ");
98 la1 = atof (tmp_ptr);
99 tmp_ptr = strtok (NULL, " ");
100 la5 = atof (tmp_ptr);
101 tmp_ptr = strtok (NULL, " ");
102 la15 = atof (tmp_ptr);
103 }
105 fclose (fp);
106 # else
107 child_process = spopen (PATH_TO_UPTIME);
108 if (child_process == NULL) {
109 printf (_("Error opening %s\n"), PATH_TO_UPTIME);
110 return STATE_UNKNOWN;
111 }
112 child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r");
113 if (child_stderr == NULL) {
114 printf (_("Could not open stderr for %s\n"), PATH_TO_UPTIME);
115 }
116 fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process);
117 sscanf (input_buffer, "%*[^l]load average: %f, %f, %f", &la1, &la5, &la15);
119 result = spclose (child_process);
120 if (result) {
121 printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME);
122 return STATE_UNKNOWN;
123 }
124 # endif
125 #endif
128 if ((la1 < 0.0) || (la5 < 0.0) || (la15 < 0.0)) {
129 #if HAVE_GETLOADAVG==1
130 printf (_("Error in getloadavg()\n"));
131 #else
132 # if HAVE_PROC_LOADAVG==1
133 printf (_("Error processing %s\n"), PROC_LOADAVG);
134 # else
135 printf (_("Error processing %s\n"), PATH_TO_UPTIME);
136 # endif
137 #endif
138 return STATE_UNKNOWN;
139 }
141 asprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15);
143 if ((la1 >= cload1) || (la5 >= cload5) || (la15 >= cload15))
144 result = STATE_CRITICAL;
145 else if ((la1 >= wload1) || (la5 >= wload5) || (la15 >= wload15))
146 result = STATE_WARNING;
147 else
148 result = STATE_OK;
150 die (result,
151 "%s - %s|%s %s %s\n",
152 state_text (result),
153 status_line,
154 fperfdata ("load1", la1, "", (int)wload1, wload1, (int)cload1, cload1, TRUE, 0, FALSE, 0),
155 fperfdata ("load5", la5, "", (int)wload5, wload5, (int)cload5, cload5, TRUE, 0, FALSE, 0),
156 fperfdata ("load15", la15, "", (int)wload15, wload15, (int)cload15, cload15, TRUE, 0, FALSE, 0));
157 return STATE_OK;
158 }
162 /* process command-line arguments */
163 int
164 process_arguments (int argc, char **argv)
165 {
166 int c = 0;
168 int option = 0;
169 static struct option longopts[] = {
170 {"warning", required_argument, 0, 'w'},
171 {"critical", required_argument, 0, 'c'},
172 {"version", no_argument, 0, 'V'},
173 {"help", no_argument, 0, 'h'},
174 {0, 0, 0, 0}
175 };
177 if (argc < 2)
178 return ERROR;
180 while (1) {
181 c = getopt_long (argc, argv, "Vhc:w:", longopts, &option);
183 if (c == -1 || c == EOF)
184 break;
186 switch (c) {
187 case 'w': /* warning time threshold */
188 if (is_intnonneg (optarg)) {
189 wload1 = atof (optarg);
190 wload5 = atof (optarg);
191 wload15 = atof (optarg);
192 break;
193 }
194 else if (strstr (optarg, ",") &&
195 sscanf (optarg, "%f,%f,%f", &wload1, &wload5, &wload15) == 3)
196 break;
197 else if (strstr (optarg, ":") &&
198 sscanf (optarg, "%f:%f:%f", &wload1, &wload5, &wload15) == 3)
199 break;
200 else
201 usage (_("Warning threshold must be float or float triplet!\n"));
202 break;
203 case 'c': /* critical time threshold */
204 if (is_intnonneg (optarg)) {
205 cload1 = atof (optarg);
206 cload5 = atof (optarg);
207 cload15 = atof (optarg);
208 break;
209 }
210 else if (strstr (optarg, ",") &&
211 sscanf (optarg, "%f,%f,%f", &cload1, &cload5, &cload15) == 3)
212 break;
213 else if (strstr (optarg, ":") &&
214 sscanf (optarg, "%f:%f:%f", &cload1, &cload5, &cload15) == 3)
215 break;
216 else
217 usage (_("Critical threshold must be float or float triplet!\n"));
218 break;
219 case 'V': /* version */
220 print_revision (progname, revision);
221 exit (STATE_OK);
222 case 'h': /* help */
223 print_help ();
224 exit (STATE_OK);
225 case '?': /* help */
226 printf (_("%s: Unknown argument: %s\n\n"), progname, optarg);
227 print_usage ();
228 exit (STATE_UNKNOWN);
229 }
230 }
232 c = optind;
233 if (c == argc)
234 return validate_arguments ();
235 if (wload1 < 0 && is_nonnegative (argv[c]))
236 wload1 = atof (argv[c++]);
238 if (c == argc)
239 return validate_arguments ();
240 if (cload1 < 0 && is_nonnegative (argv[c]))
241 cload1 = atof (argv[c++]);
243 if (c == argc)
244 return validate_arguments ();
245 if (wload5 < 0 && is_nonnegative (argv[c]))
246 wload5 = atof (argv[c++]);
248 if (c == argc)
249 return validate_arguments ();
250 if (cload5 < 0 && is_nonnegative (argv[c]))
251 cload5 = atof (argv[c++]);
253 if (c == argc)
254 return validate_arguments ();
255 if (wload15 < 0 && is_nonnegative (argv[c]))
256 wload15 = atof (argv[c++]);
258 if (c == argc)
259 return validate_arguments ();
260 if (cload15 < 0 && is_nonnegative (argv[c]))
261 cload15 = atof (argv[c++]);
263 return validate_arguments ();
264 }
268 int
269 validate_arguments (void)
270 {
271 if (wload1 < 0)
272 usage (_("Warning threshold for 1-minute load average is not specified\n"));
273 if (wload5 < 0)
274 usage (_("Warning threshold for 5-minute load average is not specified\n"));
275 if (wload15 < 0)
276 usage (_("Warning threshold for 15-minute load average is not specified\n"));
277 if (cload1 < 0)
278 usage (_("Critical threshold for 1-minute load average is not specified\n"));
279 if (cload5 < 0)
280 usage (_("Critical threshold for 5-minute load average is not specified\n"));
281 if (cload15 < 0)
282 usage (_("Critical threshold for 15-minute load average is not specified\n"));
283 if (wload1 > cload1)
284 usage (_("Parameter inconsistency: 1-minute \"warning load\" greater than \"critical load\".\n"));
285 if (wload5 > cload5)
286 usage (_("Parameter inconsistency: 5-minute \"warning load\" greater than \"critical load\".\n"));
287 if (wload15 > cload15)
288 usage (_("Parameter inconsistency: 15-minute \"warning load\" greater than \"critical load\".\n"));
289 return OK;
290 }
294 void
295 print_help (void)
296 {
297 print_revision (progname, revision);
299 printf ("Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>\n");
300 printf (COPYRIGHT, copyright, email);
302 printf (_("This plugin tests the current system load average.\n\n"));
304 print_usage ();
306 printf (_(UT_HELP_VRSN));
308 printf (_("\
309 -w, --warning=WLOAD1,WLOAD5,WLOAD15\n\
310 Exit with WARNING status if load average exceeds WLOADn\n\
311 -c, --critical=CLOAD1,CLOAD5,CLOAD15\n\
312 Exit with CRITICAL status if load average exceed CLOADn\n\n\
313 the load average format is the same used by \"uptime\" and \"w\"\n\n"));
315 printf (_(UT_SUPPORT));
316 }
318 void
319 print_usage (void)
320 {
321 printf (_("Usage: %s -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n"),
322 progname);
323 printf (_(UT_HLP_VRS), progname, progname);
324 }