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-2004";
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 = STATE_UNKNOWN;
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 usage4 (_("Could not parse arguments"));
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 fperfdata ("load1", la1, "", (int)wload1, wload1, (int)cload1, cload1, TRUE, 0, FALSE, 0),
156 fperfdata ("load5", la5, "", (int)wload5, wload5, (int)cload5, cload5, TRUE, 0, FALSE, 0),
157 fperfdata ("load15", la15, "", (int)wload15, wload15, (int)cload15, cload15, TRUE, 0, FALSE, 0));
158 return STATE_OK;
159 }
163 /* process command-line arguments */
164 int
165 process_arguments (int argc, char **argv)
166 {
167 int c = 0;
169 int option = 0;
170 static struct option longopts[] = {
171 {"warning", required_argument, 0, 'w'},
172 {"critical", required_argument, 0, 'c'},
173 {"version", no_argument, 0, 'V'},
174 {"help", no_argument, 0, 'h'},
175 {0, 0, 0, 0}
176 };
178 if (argc < 2)
179 return ERROR;
181 while (1) {
182 c = getopt_long (argc, argv, "Vhc:w:", longopts, &option);
184 if (c == -1 || c == EOF)
185 break;
187 switch (c) {
188 case 'w': /* warning time threshold */
189 if (is_intnonneg (optarg)) {
190 wload1 = atof (optarg);
191 wload5 = atof (optarg);
192 wload15 = atof (optarg);
193 break;
194 }
195 else if (strstr (optarg, ",") &&
196 sscanf (optarg, "%f,%f,%f", &wload1, &wload5, &wload15) == 3)
197 break;
198 else if (strstr (optarg, ":") &&
199 sscanf (optarg, "%f:%f:%f", &wload1, &wload5, &wload15) == 3)
200 break;
201 else
202 usage (_("Warning threshold must be float or float triplet!\n"));
203 break;
204 case 'c': /* critical time threshold */
205 if (is_intnonneg (optarg)) {
206 cload1 = atof (optarg);
207 cload5 = atof (optarg);
208 cload15 = atof (optarg);
209 break;
210 }
211 else if (strstr (optarg, ",") &&
212 sscanf (optarg, "%f,%f,%f", &cload1, &cload5, &cload15) == 3)
213 break;
214 else if (strstr (optarg, ":") &&
215 sscanf (optarg, "%f:%f:%f", &cload1, &cload5, &cload15) == 3)
216 break;
217 else
218 usage (_("Critical threshold must be float or float triplet!\n"));
219 break;
220 case 'V': /* version */
221 print_revision (progname, revision);
222 exit (STATE_OK);
223 case 'h': /* help */
224 print_help ();
225 exit (STATE_OK);
226 case '?': /* help */
227 usage2 (_("Unknown argument"), optarg);
228 }
229 }
231 c = optind;
232 if (c == argc)
233 return validate_arguments ();
234 if (wload1 < 0 && is_nonnegative (argv[c]))
235 wload1 = atof (argv[c++]);
237 if (c == argc)
238 return validate_arguments ();
239 if (cload1 < 0 && is_nonnegative (argv[c]))
240 cload1 = atof (argv[c++]);
242 if (c == argc)
243 return validate_arguments ();
244 if (wload5 < 0 && is_nonnegative (argv[c]))
245 wload5 = atof (argv[c++]);
247 if (c == argc)
248 return validate_arguments ();
249 if (cload5 < 0 && is_nonnegative (argv[c]))
250 cload5 = atof (argv[c++]);
252 if (c == argc)
253 return validate_arguments ();
254 if (wload15 < 0 && is_nonnegative (argv[c]))
255 wload15 = atof (argv[c++]);
257 if (c == argc)
258 return validate_arguments ();
259 if (cload15 < 0 && is_nonnegative (argv[c]))
260 cload15 = atof (argv[c++]);
262 return validate_arguments ();
263 }
267 int
268 validate_arguments (void)
269 {
270 if (wload1 < 0)
271 usage (_("Warning threshold for 1-minute load average is not specified\n"));
272 if (wload5 < 0)
273 usage (_("Warning threshold for 5-minute load average is not specified\n"));
274 if (wload15 < 0)
275 usage (_("Warning threshold for 15-minute load average is not specified\n"));
276 if (cload1 < 0)
277 usage (_("Critical threshold for 1-minute load average is not specified\n"));
278 if (cload5 < 0)
279 usage (_("Critical threshold for 5-minute load average is not specified\n"));
280 if (cload15 < 0)
281 usage (_("Critical threshold for 15-minute load average is not specified\n"));
282 if (wload1 > cload1)
283 usage (_("Parameter inconsistency: 1-minute \"warning load\" greater than \"critical load\".\n"));
284 if (wload5 > cload5)
285 usage (_("Parameter inconsistency: 5-minute \"warning load\" greater than \"critical load\".\n"));
286 if (wload15 > cload15)
287 usage (_("Parameter inconsistency: 15-minute \"warning load\" greater than \"critical load\".\n"));
288 return OK;
289 }
293 void
294 print_help (void)
295 {
296 print_revision (progname, revision);
298 printf ("Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>\n");
299 printf (COPYRIGHT, copyright, email);
301 printf (_("This plugin tests the current system load average.\n\n"));
303 print_usage ();
305 printf (_(UT_HELP_VRSN));
307 printf (_("\
308 -w, --warning=WLOAD1,WLOAD5,WLOAD15\n\
309 Exit with WARNING status if load average exceeds WLOADn\n\
310 -c, --critical=CLOAD1,CLOAD5,CLOAD15\n\
311 Exit with CRITICAL status if load average exceed CLOADn\n\n\
312 the load average format is the same used by \"uptime\" and \"w\"\n\n"));
314 printf (_(UT_SUPPORT));
315 }
317 void
318 print_usage (void)
319 {
320 printf ("Usage: %s -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname);
321 }