summaryrefslogtreecommitdiffstats
path: root/plugins/check_load.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/check_load.c')
-rw-r--r--plugins/check_load.c173
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
31const char *progname = "check_load"; 31const char *progname = "check_load";
32const char *copyright = "1999-2007"; 32const char *copyright = "1999-2022";
33const char *email = "devel@monitoring-plugins.org"; 33const 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);
52static int validate_arguments (void); 55static int validate_arguments (void);
53void print_help (void); 56void print_help (void);
54void print_usage (void); 57void print_usage (void);
58static int print_top_consuming_processes();
59
60static int n_procs_to_show = 0;
55 61
56/* strictly for pretty-print usage in loops */ 62/* strictly for pretty-print usage in loops */
57static const int nums[3] = { 1, 5, 15 }; 63static 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
66char *status_line; 72char *status_line;
67int take_into_account_cpus = 0; 73bool take_into_account_cpus = false;
68 74
69static void 75static void
70get_threshold(char *arg, double *th) 76get_threshold(char *arg, double *th)
@@ -97,11 +103,11 @@ get_threshold(char *arg, double *th)
97int 103int
98main (int argc, char **argv) 104main (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
282static int 318static int
283validate_arguments (void) 319validate_arguments (void)
284{ 320{
@@ -299,7 +335,6 @@ validate_arguments (void)
299} 335}
300 336
301 337
302
303void 338void
304print_help (void) 339print_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)
331void 369void
332print_usage (void) 370print_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
377int 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
397static 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}