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