diff options
Diffstat (limited to 'plugins/check_load.c')
-rw-r--r-- | plugins/check_load.c | 173 |
1 files changed, 127 insertions, 46 deletions
diff --git a/plugins/check_load.c b/plugins/check_load.c index a96435f4..313df8ad 100644 --- a/plugins/check_load.c +++ b/plugins/check_load.c | |||
@@ -1,40 +1,43 @@ | |||
1 | /***************************************************************************** | 1 | /***************************************************************************** |
2 | * | 2 | * |
3 | * Monitoring check_load plugin | 3 | * Monitoring check_load plugin |
4 | * | 4 | * |
5 | * License: GPL | 5 | * License: GPL |
6 | * Copyright (c) 1999-2007 Monitoring Plugins Development Team | 6 | * Copyright (c) 1999-2007 Monitoring Plugins Development Team |
7 | * | 7 | * |
8 | * Description: | 8 | * Description: |
9 | * | 9 | * |
10 | * This file contains the check_load plugin | 10 | * This file contains the check_load plugin |
11 | * | 11 | * |
12 | * This plugin tests the current system load average. | 12 | * This plugin tests the current system load average. |
13 | * | 13 | * |
14 | * | 14 | * |
15 | * This program is free software: you can redistribute it and/or modify | 15 | * This program is free software: you can redistribute it and/or modify |
16 | * it under the terms of the GNU General Public License as published by | 16 | * it under the terms of the GNU General Public License as published by |
17 | * the Free Software Foundation, either version 3 of the License, or | 17 | * the Free Software Foundation, either version 3 of the License, or |
18 | * (at your option) any later version. | 18 | * (at your option) any later version. |
19 | * | 19 | * |
20 | * This program is distributed in the hope that it will be useful, | 20 | * This program is distributed in the hope that it will be useful, |
21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 21 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 22 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
23 | * GNU General Public License for more details. | 23 | * GNU General Public License for more details. |
24 | * | 24 | * |
25 | * You should have received a copy of the GNU General Public License | 25 | * You should have received a copy of the GNU General Public License |
26 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 26 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
27 | * | 27 | * |
28 | * | 28 | * |
29 | *****************************************************************************/ | 29 | *****************************************************************************/ |
30 | 30 | ||
31 | const char *progname = "check_load"; | 31 | const char *progname = "check_load"; |
32 | const char *copyright = "1999-2007"; | 32 | const char *copyright = "1999-2022"; |
33 | const char *email = "devel@monitoring-plugins.org"; | 33 | const char *email = "devel@monitoring-plugins.org"; |
34 | 34 | ||
35 | #include "common.h" | 35 | #include "./common.h" |
36 | #include "utils.h" | 36 | #include "./runcmd.h" |
37 | #include "popen.h" | 37 | #include "./utils.h" |
38 | #include "./popen.h" | ||
39 | |||
40 | #include <string.h> | ||
38 | 41 | ||
39 | #ifdef HAVE_SYS_LOADAVG_H | 42 | #ifdef HAVE_SYS_LOADAVG_H |
40 | #include <sys/loadavg.h> | 43 | #include <sys/loadavg.h> |
@@ -52,6 +55,9 @@ static int process_arguments (int argc, char **argv); | |||
52 | static int validate_arguments (void); | 55 | static int validate_arguments (void); |
53 | void print_help (void); | 56 | void print_help (void); |
54 | void print_usage (void); | 57 | void print_usage (void); |
58 | static int print_top_consuming_processes(); | ||
59 | |||
60 | static int n_procs_to_show = 0; | ||
55 | 61 | ||
56 | /* strictly for pretty-print usage in loops */ | 62 | /* strictly for pretty-print usage in loops */ |
57 | static const int nums[3] = { 1, 5, 15 }; | 63 | static const int nums[3] = { 1, 5, 15 }; |
@@ -64,7 +70,7 @@ double cload[3] = { 0.0, 0.0, 0.0 }; | |||
64 | #define la15 la[2] | 70 | #define la15 la[2] |
65 | 71 | ||
66 | char *status_line; | 72 | char *status_line; |
67 | int take_into_account_cpus = 0; | 73 | bool take_into_account_cpus = false; |
68 | 74 | ||
69 | static void | 75 | static void |
70 | get_threshold(char *arg, double *th) | 76 | get_threshold(char *arg, double *th) |
@@ -97,11 +103,11 @@ get_threshold(char *arg, double *th) | |||
97 | int | 103 | int |
98 | main (int argc, char **argv) | 104 | main (int argc, char **argv) |
99 | { | 105 | { |
100 | int result; | 106 | int result = -1; |
101 | int i; | 107 | int i; |
102 | long numcpus; | 108 | long numcpus; |
103 | 109 | ||
104 | double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */ | 110 | double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about uninitialized arrays */ |
105 | #ifndef HAVE_GETLOADAVG | 111 | #ifndef HAVE_GETLOADAVG |
106 | char input_buffer[MAX_INPUT_BUFFER]; | 112 | char input_buffer[MAX_INPUT_BUFFER]; |
107 | # ifdef HAVE_PROC_LOADAVG | 113 | # ifdef HAVE_PROC_LOADAVG |
@@ -160,7 +166,7 @@ main (int argc, char **argv) | |||
160 | sscanf (input_buffer, "%*[^l]load averages: %lf, %lf, %lf", &la1, &la5, &la15); | 166 | sscanf (input_buffer, "%*[^l]load averages: %lf, %lf, %lf", &la1, &la5, &la15); |
161 | } | 167 | } |
162 | else { | 168 | else { |
163 | printf (_("could not parse load from uptime: %s\n"), result, PATH_TO_UPTIME); | 169 | printf (_("could not parse load from uptime %s: %d\n"), PATH_TO_UPTIME, result); |
164 | return STATE_UNKNOWN; | 170 | return STATE_UNKNOWN; |
165 | } | 171 | } |
166 | 172 | ||
@@ -172,13 +178,6 @@ main (int argc, char **argv) | |||
172 | # endif | 178 | # endif |
173 | #endif | 179 | #endif |
174 | 180 | ||
175 | if (take_into_account_cpus == 1) { | ||
176 | if ((numcpus = GET_NUMBER_OF_CPUS()) > 0) { | ||
177 | la[0] = la[0] / numcpus; | ||
178 | la[1] = la[1] / numcpus; | ||
179 | la[2] = la[2] / numcpus; | ||
180 | } | ||
181 | } | ||
182 | if ((la[0] < 0.0) || (la[1] < 0.0) || (la[2] < 0.0)) { | 181 | if ((la[0] < 0.0) || (la[1] < 0.0) || (la[2] < 0.0)) { |
183 | #ifdef HAVE_GETLOADAVG | 182 | #ifdef HAVE_GETLOADAVG |
184 | printf (_("Error in getloadavg()\n")); | 183 | printf (_("Error in getloadavg()\n")); |
@@ -196,20 +195,54 @@ main (int argc, char **argv) | |||
196 | result = STATE_OK; | 195 | result = STATE_OK; |
197 | 196 | ||
198 | xasprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15); | 197 | xasprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15); |
198 | xasprintf(&status_line, ("total %s"), status_line); | ||
199 | |||
200 | |||
201 | double scaled_la[3] = { 0.0, 0.0, 0.0 }; | ||
202 | bool is_using_scaled_load_values = false; | ||
203 | |||
204 | if (take_into_account_cpus == true && (numcpus = GET_NUMBER_OF_CPUS()) > 0) { | ||
205 | is_using_scaled_load_values = true; | ||
206 | |||
207 | scaled_la[0] = la[0] / numcpus; | ||
208 | scaled_la[1] = la[1] / numcpus; | ||
209 | scaled_la[2] = la[2] / numcpus; | ||
210 | |||
211 | char *tmp = NULL; | ||
212 | xasprintf(&tmp, _("load average: %.2f, %.2f, %.2f"), scaled_la[0], scaled_la[1], scaled_la[2]); | ||
213 | xasprintf(&status_line, "scaled %s - %s", tmp, status_line); | ||
214 | } | ||
199 | 215 | ||
200 | for(i = 0; i < 3; i++) { | 216 | for(i = 0; i < 3; i++) { |
201 | if(la[i] > cload[i]) { | 217 | if (is_using_scaled_load_values) { |
202 | result = STATE_CRITICAL; | 218 | if(scaled_la[i] > cload[i]) { |
203 | break; | 219 | result = STATE_CRITICAL; |
220 | break; | ||
221 | } | ||
222 | else if(scaled_la[i] > wload[i]) result = STATE_WARNING; | ||
223 | } else { | ||
224 | if(la[i] > cload[i]) { | ||
225 | result = STATE_CRITICAL; | ||
226 | break; | ||
227 | } | ||
228 | else if(la[i] > wload[i]) result = STATE_WARNING; | ||
204 | } | 229 | } |
205 | else if(la[i] > wload[i]) result = STATE_WARNING; | ||
206 | } | 230 | } |
207 | 231 | ||
208 | printf("%s - %s|", state_text(result), status_line); | 232 | printf("LOAD %s - %s|", state_text(result), status_line); |
209 | for(i = 0; i < 3; i++) | 233 | for(i = 0; i < 3; i++) { |
210 | printf("load%d=%.3f;%.3f;%.3f;0; ", nums[i], la[i], wload[i], cload[i]); | 234 | if (is_using_scaled_load_values) { |
235 | printf("load%d=%.3f;;;0; ", nums[i], la[i]); | ||
236 | printf("scaled_load%d=%.3f;%.3f;%.3f;0; ", nums[i], scaled_la[i], wload[i], cload[i]); | ||
237 | } else { | ||
238 | printf("load%d=%.3f;%.3f;%.3f;0; ", nums[i], la[i], wload[i], cload[i]); | ||
239 | } | ||
240 | } | ||
211 | 241 | ||
212 | putchar('\n'); | 242 | putchar('\n'); |
243 | if (n_procs_to_show > 0) { | ||
244 | print_top_consuming_processes(); | ||
245 | } | ||
213 | return result; | 246 | return result; |
214 | } | 247 | } |
215 | 248 | ||
@@ -227,6 +260,7 @@ process_arguments (int argc, char **argv) | |||
227 | {"percpu", no_argument, 0, 'r'}, | 260 | {"percpu", no_argument, 0, 'r'}, |
228 | {"version", no_argument, 0, 'V'}, | 261 | {"version", no_argument, 0, 'V'}, |
229 | {"help", no_argument, 0, 'h'}, | 262 | {"help", no_argument, 0, 'h'}, |
263 | {"procs-to-show", required_argument, 0, 'n'}, | ||
230 | {0, 0, 0, 0} | 264 | {0, 0, 0, 0} |
231 | }; | 265 | }; |
232 | 266 | ||
@@ -234,7 +268,7 @@ process_arguments (int argc, char **argv) | |||
234 | return ERROR; | 268 | return ERROR; |
235 | 269 | ||
236 | while (1) { | 270 | while (1) { |
237 | c = getopt_long (argc, argv, "Vhrc:w:", longopts, &option); | 271 | c = getopt_long (argc, argv, "Vhrc:w:n:", longopts, &option); |
238 | 272 | ||
239 | if (c == -1 || c == EOF) | 273 | if (c == -1 || c == EOF) |
240 | break; | 274 | break; |
@@ -247,7 +281,7 @@ process_arguments (int argc, char **argv) | |||
247 | get_threshold(optarg, cload); | 281 | get_threshold(optarg, cload); |
248 | break; | 282 | break; |
249 | case 'r': /* Divide load average by number of CPUs */ | 283 | case 'r': /* Divide load average by number of CPUs */ |
250 | take_into_account_cpus = 1; | 284 | take_into_account_cpus = true; |
251 | break; | 285 | break; |
252 | case 'V': /* version */ | 286 | case 'V': /* version */ |
253 | print_revision (progname, NP_VERSION); | 287 | print_revision (progname, NP_VERSION); |
@@ -255,6 +289,9 @@ process_arguments (int argc, char **argv) | |||
255 | case 'h': /* help */ | 289 | case 'h': /* help */ |
256 | print_help (); | 290 | print_help (); |
257 | exit (STATE_UNKNOWN); | 291 | exit (STATE_UNKNOWN); |
292 | case 'n': | ||
293 | n_procs_to_show = atoi(optarg); | ||
294 | break; | ||
258 | case '?': /* help */ | 295 | case '?': /* help */ |
259 | usage5 (); | 296 | usage5 (); |
260 | } | 297 | } |
@@ -278,7 +315,6 @@ process_arguments (int argc, char **argv) | |||
278 | } | 315 | } |
279 | 316 | ||
280 | 317 | ||
281 | |||
282 | static int | 318 | static int |
283 | validate_arguments (void) | 319 | validate_arguments (void) |
284 | { | 320 | { |
@@ -299,7 +335,6 @@ validate_arguments (void) | |||
299 | } | 335 | } |
300 | 336 | ||
301 | 337 | ||
302 | |||
303 | void | 338 | void |
304 | print_help (void) | 339 | print_help (void) |
305 | { | 340 | { |
@@ -310,7 +345,7 @@ print_help (void) | |||
310 | 345 | ||
311 | printf (_("This plugin tests the current system load average.")); | 346 | printf (_("This plugin tests the current system load average.")); |
312 | 347 | ||
313 | printf ("\n\n"); | 348 | printf ("\n\n"); |
314 | 349 | ||
315 | print_usage (); | 350 | print_usage (); |
316 | 351 | ||
@@ -318,12 +353,15 @@ print_help (void) | |||
318 | printf (UT_EXTRA_OPTS); | 353 | printf (UT_EXTRA_OPTS); |
319 | 354 | ||
320 | printf (" %s\n", "-w, --warning=WLOAD1,WLOAD5,WLOAD15"); | 355 | printf (" %s\n", "-w, --warning=WLOAD1,WLOAD5,WLOAD15"); |
321 | printf (" %s\n", _("Exit with WARNING status if load average exceeds WLOADn")); | 356 | printf (" %s\n", _("Exit with WARNING status if load average exceeds WLOADn")); |
322 | printf (" %s\n", "-c, --critical=CLOAD1,CLOAD5,CLOAD15"); | 357 | printf (" %s\n", "-c, --critical=CLOAD1,CLOAD5,CLOAD15"); |
323 | printf (" %s\n", _("Exit with CRITICAL status if load average exceed CLOADn")); | 358 | printf (" %s\n", _("Exit with CRITICAL status if load average exceed CLOADn")); |
324 | printf (" %s\n", _("the load average format is the same used by \"uptime\" and \"w\"")); | 359 | printf (" %s\n", _("the load average format is the same used by \"uptime\" and \"w\"")); |
325 | printf (" %s\n", "-r, --percpu"); | 360 | printf (" %s\n", "-r, --percpu"); |
326 | printf (" %s\n", _("Divide the load averages by the number of CPUs (when possible)")); | 361 | printf (" %s\n", _("Divide the load averages by the number of CPUs (when possible)")); |
362 | printf (" %s\n", "-n, --procs-to-show=NUMBER_OF_PROCS"); | ||
363 | printf (" %s\n", _("Number of processes to show when printing the top consuming processes.")); | ||
364 | printf (" %s\n", _("NUMBER_OF_PROCS=0 disables this feature. Default value is 0")); | ||
327 | 365 | ||
328 | printf (UT_SUPPORT); | 366 | printf (UT_SUPPORT); |
329 | } | 367 | } |
@@ -331,6 +369,49 @@ print_help (void) | |||
331 | void | 369 | void |
332 | print_usage (void) | 370 | print_usage (void) |
333 | { | 371 | { |
334 | printf ("%s\n", _("Usage:")); | 372 | printf ("%s\n", _("Usage:")); |
335 | printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname); | 373 | printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15 [-n NUMBER_OF_PROCS]\n", progname); |
374 | } | ||
375 | |||
376 | #ifdef PS_USES_PROCPCPU | ||
377 | int cmpstringp(const void *p1, const void *p2) { | ||
378 | int procuid = 0; | ||
379 | int procpid = 0; | ||
380 | int procppid = 0; | ||
381 | int procvsz = 0; | ||
382 | int procrss = 0; | ||
383 | float procpcpu = 0; | ||
384 | char procstat[8]; | ||
385 | #ifdef PS_USES_PROCETIME | ||
386 | char procetime[MAX_INPUT_BUFFER]; | ||
387 | #endif /* PS_USES_PROCETIME */ | ||
388 | char procprog[MAX_INPUT_BUFFER]; | ||
389 | int pos; | ||
390 | sscanf (* (char * const *) p1, PS_FORMAT, PS_VARLIST); | ||
391 | float procpcpu1 = procpcpu; | ||
392 | sscanf (* (char * const *) p2, PS_FORMAT, PS_VARLIST); | ||
393 | return procpcpu1 < procpcpu; | ||
394 | } | ||
395 | #endif /* PS_USES_PROCPCPU */ | ||
396 | |||
397 | static int print_top_consuming_processes() { | ||
398 | int i = 0; | ||
399 | struct output chld_out, chld_err; | ||
400 | if(np_runcmd(PS_COMMAND, &chld_out, &chld_err, 0) != 0){ | ||
401 | fprintf(stderr, _("'%s' exited with non-zero status.\n"), PS_COMMAND); | ||
402 | return STATE_UNKNOWN; | ||
403 | } | ||
404 | if (chld_out.lines < 2) { | ||
405 | fprintf(stderr, _("some error occurred getting procs list.\n")); | ||
406 | return STATE_UNKNOWN; | ||
407 | } | ||
408 | #ifdef PS_USES_PROCPCPU | ||
409 | qsort(chld_out.line + 1, chld_out.lines - 1, sizeof(char*), cmpstringp); | ||
410 | #endif /* PS_USES_PROCPCPU */ | ||
411 | int lines_to_show = chld_out.lines < (size_t)(n_procs_to_show + 1) | ||
412 | ? (int)chld_out.lines : n_procs_to_show + 1; | ||
413 | for (i = 0; i < lines_to_show; i += 1) { | ||
414 | printf("%s\n", chld_out.line[i]); | ||
415 | } | ||
416 | return OK; | ||
336 | } | 417 | } |