1 /*****************************************************************************
3 * Nagios check_load plugin
6 * Copyright (c) 1999-2007 Nagios Plugins Development Team
8 * Last Modified: $Date$
12 * This file contains the check_load plugin
14 * This plugin tests the current system load average.
17 * This program is free software: you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation, either version 3 of the License, or
20 * (at your option) any later version.
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
27 * You should have received a copy of the GNU General Public License
28 * along with this program. If not, see <http://www.gnu.org/licenses/>.
32 *****************************************************************************/
34 const char *progname
= "check_load";
35 const char *revision
= "$Revision$";
36 const char *copyright
= "1999-2007";
37 const char *email
= "nagiosplug-devel@lists.sourceforge.net";
43 #ifdef HAVE_SYS_LOADAVG_H
44 #include <sys/loadavg.h>
47 /* needed for compilation under NetBSD, as suggested by Andy Doran */
49 #define LOADAVG_1MIN 0
50 #define LOADAVG_5MIN 1
51 #define LOADAVG_15MIN 2
52 #endif /* !defined LOADAVG_1MIN */
55 static int process_arguments (int argc
, char **argv
);
56 static int validate_arguments (void);
57 void print_help (void);
58 void print_usage (void);
60 /* strictly for pretty-print usage in loops */
61 static const int nums
[3] = { 1, 5, 15 };
63 /* provide some fairly sane defaults */
64 double wload
[3] = { 0.0, 0.0, 0.0 };
65 double cload
[3] = { 0.0, 0.0, 0.0 };
71 int take_into_account_cpus
= 0;
74 get_threshold(char *arg
, double *th
)
81 for(i
= 0; i
< 3; i
++) {
82 th
[i
] = strtod(str
, &p
);
87 if(n
<= (size_t)(str
- arg
)) break;
90 /* empty argument or non-floatish, so warn about it and die */
91 if(!i
&& !valid
) usage (_("Warning threshold must be float or float triplet!\n"));
94 /* one or more numbers were given, so fill array with last
95 * we got (most likely to NOT produce the least expected result) */
96 for(n
= i
; n
< 3; n
++) th
[n
] = th
[i
];
102 main (int argc
, char **argv
)
108 double la
[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */
109 #ifndef HAVE_GETLOADAVG
110 char input_buffer
[MAX_INPUT_BUFFER
];
111 # ifdef HAVE_PROC_LOADAVG
117 setlocale (LC_ALL
, "");
118 bindtextdomain (PACKAGE
, LOCALEDIR
);
119 textdomain (PACKAGE
);
120 setlocale(LC_NUMERIC
, "POSIX");
122 /* Parse extra opts if any */
123 argv
= np_extra_opts (&argc
, argv
, progname
);
125 if (process_arguments (argc
, argv
) == ERROR
)
126 usage4 (_("Could not parse arguments"));
128 #ifdef HAVE_GETLOADAVG
129 result
= getloadavg (la
, 3);
131 return STATE_UNKNOWN
;
133 # ifdef HAVE_PROC_LOADAVG
134 fp
= fopen (PROC_LOADAVG
, "r");
136 printf (_("Error opening %s\n"), PROC_LOADAVG
);
137 return STATE_UNKNOWN
;
140 while (fgets (input_buffer
, MAX_INPUT_BUFFER
- 1, fp
)) {
141 str
= (char *)input_buffer
;
142 for(i
= 0; i
< 3; i
++) {
143 la
[i
] = strtod(str
, &next
);
150 child_process
= spopen (PATH_TO_UPTIME
);
151 if (child_process
== NULL
) {
152 printf (_("Error opening %s\n"), PATH_TO_UPTIME
);
153 return STATE_UNKNOWN
;
155 child_stderr
= fdopen (child_stderr_array
[fileno (child_process
)], "r");
156 if (child_stderr
== NULL
) {
157 printf (_("Could not open stderr for %s\n"), PATH_TO_UPTIME
);
159 fgets (input_buffer
, MAX_INPUT_BUFFER
- 1, child_process
);
160 sscanf (input_buffer
, "%*[^l]load average: %lf, %lf, %lf", &la1
, &la5
, &la15
);
162 result
= spclose (child_process
);
164 printf (_("Error code %d returned in %s\n"), result
, PATH_TO_UPTIME
);
165 return STATE_UNKNOWN
;
170 if (take_into_account_cpus
== 1) {
171 if ((numcpus
= GET_NUMBER_OF_CPUS()) > 0) {
172 la
[0] = la
[0] / numcpus
;
173 la
[1] = la
[1] / numcpus
;
174 la
[2] = la
[2] / numcpus
;
177 if ((la
[0] < 0.0) || (la
[1] < 0.0) || (la
[2] < 0.0)) {
178 #ifdef HAVE_GETLOADAVG
179 printf (_("Error in getloadavg()\n"));
181 # ifdef HAVE_PROC_LOADAVG
182 printf (_("Error processing %s\n"), PROC_LOADAVG
);
184 printf (_("Error processing %s\n"), PATH_TO_UPTIME
);
187 return STATE_UNKNOWN
;
190 /* we got this far, so assume OK until we've measured */
193 asprintf(&status_line
, _("load average: %.2f, %.2f, %.2f"), la1
, la5
, la15
);
195 for(i
= 0; i
< 3; i
++) {
196 if(la
[i
] > cload
[i
]) {
197 result
= STATE_CRITICAL
;
200 else if(la
[i
] > wload
[i
]) result
= STATE_WARNING
;
203 printf("%s - %s|", state_text(result
), status_line
);
204 for(i
= 0; i
< 3; i
++)
205 printf("load%d=%.3f;%.3f;%.3f;0; ", nums
[i
], la
[i
], wload
[i
], cload
[i
]);
212 /* process command-line arguments */
214 process_arguments (int argc
, char **argv
)
219 static struct option longopts
[] = {
220 {"warning", required_argument
, 0, 'w'},
221 {"critical", required_argument
, 0, 'c'},
222 {"percpu", no_argument
, 0, 'r'},
223 {"version", no_argument
, 0, 'V'},
224 {"help", no_argument
, 0, 'h'},
232 c
= getopt_long (argc
, argv
, "Vhrc:w:", longopts
, &option
);
234 if (c
== -1 || c
== EOF
)
238 case 'w': /* warning time threshold */
239 get_threshold(optarg
, wload
);
241 case 'c': /* critical time threshold */
242 get_threshold(optarg
, cload
);
244 case 'r': /* Divide load average by number of CPUs */
245 take_into_account_cpus
= 1;
247 case 'V': /* version */
248 print_revision (progname
, revision
);
260 return validate_arguments ();
262 /* handle the case if both arguments are missing,
263 * but not if only one is given without -c or -w flag */
265 get_threshold(argv
[c
++], wload
);
266 get_threshold(argv
[c
++], cload
);
268 else if(c
- argc
== 1) {
269 get_threshold(argv
[c
++], cload
);
272 return validate_arguments ();
278 validate_arguments (void)
282 /* match cload first, as it will give the most friendly error message
283 * if user hasn't given the -c switch properly */
284 for(i
= 0; i
< 3; i
++) {
286 die (STATE_UNKNOWN
, _("Critical threshold for %d-minute load average is not specified\n"), nums
[i
]);
288 die (STATE_UNKNOWN
, _("Warning threshold for %d-minute load average is not specified\n"), nums
[i
]);
289 if(wload
[i
] > cload
[i
])
290 die (STATE_UNKNOWN
, _("Parameter inconsistency: %d-minute \"warning load\" is greater than \"critical load\"\n"), nums
[i
]);
301 print_revision (progname
, revision
);
303 printf ("Copyright (c) 1999 Felipe Gustavo de Almeida <galmeida@linux.ime.usp.br>\n");
304 printf (COPYRIGHT
, copyright
, email
);
306 printf (_("This plugin tests the current system load average."));
312 printf (_(UT_HELP_VRSN
));
313 printf (_(UT_EXTRA_OPTS
));
315 printf (" %s\n", "-w, --warning=WLOAD1,WLOAD5,WLOAD15");
316 printf (" %s\n", _("Exit with WARNING status if load average exceeds WLOADn"));
317 printf (" %s\n", "-c, --critical=CLOAD1,CLOAD5,CLOAD15");
318 printf (" %s\n", _("Exit with CRITICAL status if load average exceed CLOADn"));
319 printf (" %s\n", _("the load average format is the same used by \"uptime\" and \"w\""));
320 printf (" %s\n", "-r, --percpu");
321 printf (" %s\n", _("Divide the load averages by the number of CPUs (when possible)"));
325 printf ("%s\n", _("Notes:"));
326 printf (_(UT_EXTRA_OPTS_NOTES
));
329 printf (_(UT_SUPPORT
));
335 printf (_("Usage:"));
336 printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname
);