X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins%2Fcheck_load.c;h=450a4fc3bc3afa99c9017b12bb447629c0c6e2e5;hb=25d1ee331dbe4977a4a1a756c67f32bd51d9b070;hp=58113817008618dfb657e8da9546fb4e8b10d41c;hpb=22bd672d19c378f1e6124ee18e64e5a88cf53739;p=nagiosplug.git diff --git a/plugins/check_load.c b/plugins/check_load.c index 5811381..450a4fc 100644 --- a/plugins/check_load.c +++ b/plugins/check_load.c @@ -1,24 +1,35 @@ -/****************************************************************************** - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -******************************************************************************/ +/***************************************************************************** +* +* Nagios check_load plugin +* +* License: GPL +* Copyright (c) 1999-2007 Nagios Plugins Development Team +* +* Description: +* +* This file contains the check_load plugin +* +* This plugin tests the current system load average. +* +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +* +* +*****************************************************************************/ const char *progname = "check_load"; -const char *revision = "$Revision$"; -const char *copyright = "1999-2003"; +const char *copyright = "1999-2007"; const char *email = "nagiosplug-devel@lists.sourceforge.net"; #include "common.h" @@ -37,71 +48,97 @@ const char *email = "nagiosplug-devel@lists.sourceforge.net"; #endif /* !defined LOADAVG_1MIN */ -int process_arguments (int argc, char **argv); -int validate_arguments (void); +static int process_arguments (int argc, char **argv); +static int validate_arguments (void); void print_help (void); void print_usage (void); -float wload1 = -1, wload5 = -1, wload15 = -1; -float cload1 = -1, cload5 = -1, cload15 = -1; +/* strictly for pretty-print usage in loops */ +static const int nums[3] = { 1, 5, 15 }; + +/* provide some fairly sane defaults */ +double wload[3] = { 0.0, 0.0, 0.0 }; +double cload[3] = { 0.0, 0.0, 0.0 }; +#define la1 la[0] +#define la5 la[1] +#define la15 la[2] char *status_line; +int take_into_account_cpus = 0; +static void +get_threshold(char *arg, double *th) +{ + size_t i, n; + int valid = 0; + char *str = arg, *p; + + n = strlen(arg); + for(i = 0; i < 3; i++) { + th[i] = strtod(str, &p); + if(p == str) break; + + valid = 1; + str = p + 1; + if(n <= (size_t)(str - arg)) break; + } + /* empty argument or non-floatish, so warn about it and die */ + if(!i && !valid) usage (_("Warning threshold must be float or float triplet!\n")); + if(i != 2) { + /* one or more numbers were given, so fill array with last + * we got (most likely to NOT produce the least expected result) */ + for(n = i; n < 3; n++) th[n] = th[i]; + } +} - int main (int argc, char **argv) { -#if HAVE_GETLOADAVG==1 int result; + int i; + long numcpus; + double la[3] = { 0.0, 0.0, 0.0 }; /* NetBSD complains about unitialized arrays */ -#else -# if HAVE_PROC_LOADAVG==1 - FILE *fp; - char input_buffer[MAX_INPUT_BUFFER]; - char *tmp_ptr; -# else - int result; +#ifndef HAVE_GETLOADAVG char input_buffer[MAX_INPUT_BUFFER]; +# ifdef HAVE_PROC_LOADAVG + FILE *fp; + char *str, *next; # endif #endif - float la1, la5, la15; - setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); + setlocale(LC_NUMERIC, "POSIX"); + + /* Parse extra opts if any */ + argv = np_extra_opts (&argc, argv, progname); if (process_arguments (argc, argv) == ERROR) - usage ("failed processing arguments\n"); + usage4 (_("Could not parse arguments")); -#if HAVE_GETLOADAVG==1 +#ifdef HAVE_GETLOADAVG result = getloadavg (la, 3); - if (result == -1) + if (result != 3) return STATE_UNKNOWN; - la1 = la[LOADAVG_1MIN]; - la5 = la[LOADAVG_5MIN]; - la15 = la[LOADAVG_15MIN]; #else -# if HAVE_PROC_LOADAVG==1 +# ifdef HAVE_PROC_LOADAVG fp = fopen (PROC_LOADAVG, "r"); if (fp == NULL) { printf (_("Error opening %s\n"), PROC_LOADAVG); return STATE_UNKNOWN; } - la1 = la5 = la15 = -1; - while (fgets (input_buffer, MAX_INPUT_BUFFER - 1, fp)) { - tmp_ptr = strtok (input_buffer, " "); - la1 = atof (tmp_ptr); - tmp_ptr = strtok (NULL, " "); - la5 = atof (tmp_ptr); - tmp_ptr = strtok (NULL, " "); - la15 = atof (tmp_ptr); + str = (char *)input_buffer; + for(i = 0; i < 3; i++) { + la[i] = strtod(str, &next); + str = next; + } } fclose (fp); @@ -116,7 +153,7 @@ main (int argc, char **argv) printf (_("Could not open stderr for %s\n"), PATH_TO_UPTIME); } fgets (input_buffer, MAX_INPUT_BUFFER - 1, child_process); - sscanf (input_buffer, "%*[^l]load average: %f, %f, %f"), &la1, &la5, &la15); + sscanf (input_buffer, "%*[^l]load average: %lf, %lf, %lf", &la1, &la5, &la15); result = spclose (child_process); if (result) { @@ -126,11 +163,18 @@ main (int argc, char **argv) # endif #endif - if ((la1 < 0.0) || (la5 < 0.0) || (la15 < 0.0)) { -#if HAVE_GETLOADAVG==1 + if (take_into_account_cpus == 1) { + if ((numcpus = GET_NUMBER_OF_CPUS()) > 0) { + la[0] = la[0] / numcpus; + la[1] = la[1] / numcpus; + la[2] = la[2] / numcpus; + } + } + if ((la[0] < 0.0) || (la[1] < 0.0) || (la[2] < 0.0)) { +#ifdef HAVE_GETLOADAVG printf (_("Error in getloadavg()\n")); #else -# if HAVE_PROC_LOADAVG==1 +# ifdef HAVE_PROC_LOADAVG printf (_("Error processing %s\n"), PROC_LOADAVG); # else printf (_("Error processing %s\n"), PATH_TO_UPTIME); @@ -138,26 +182,31 @@ main (int argc, char **argv) #endif return STATE_UNKNOWN; } + + /* we got this far, so assume OK until we've measured */ + result = STATE_OK; + asprintf(&status_line, _("load average: %.2f, %.2f, %.2f"), la1, la5, la15); - if ((la1 >= cload1) || (la5 >= cload5) || (la15 >= cload15)) { - printf(_("CRITICAL - %s\n"), status_line); - return STATE_CRITICAL; - } - if ((la1 >= wload1) || (la5 >= wload5) || (la15 >= wload15)) { - printf (_("WARNING - %s\n"), status_line); - return STATE_WARNING; - } - printf (_("OK - %s\n"), status_line); - return STATE_OK; -} + for(i = 0; i < 3; i++) { + if(la[i] > cload[i]) { + result = STATE_CRITICAL; + break; + } + else if(la[i] > wload[i]) result = STATE_WARNING; + } + printf("%s - %s|", state_text(result), status_line); + for(i = 0; i < 3; i++) + printf("load%d=%.3f;%.3f;%.3f;0; ", nums[i], la[i], wload[i], cload[i]); + putchar('\n'); + return result; +} - /* process command-line arguments */ -int +static int process_arguments (int argc, char **argv) { int c = 0; @@ -166,6 +215,7 @@ process_arguments (int argc, char **argv) static struct option longopts[] = { {"warning", required_argument, 0, 'w'}, {"critical", required_argument, 0, 'c'}, + {"percpu", no_argument, 0, 'r'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} @@ -175,150 +225,109 @@ process_arguments (int argc, char **argv) return ERROR; while (1) { - c = getopt_long (argc, argv, "Vhc:w:", longopts, &option); + c = getopt_long (argc, argv, "Vhrc:w:", longopts, &option); if (c == -1 || c == EOF) break; switch (c) { - case 'w': /* warning time threshold */ - if (is_intnonneg (optarg)) { - wload1 = atof (optarg); - wload5 = atof (optarg); - wload15 = atof (optarg); - break; - } - else if (strstr (optarg, ",") && - sscanf (optarg, "%f,%f,%f", &wload1, &wload5, &wload15) == 3) - break; - else if (strstr (optarg, ":") && - sscanf (optarg, "%f:%f:%f", &wload1, &wload5, &wload15) == 3) - break; - else - usage (_("Warning threshold must be float or float triplet!\n")); + case 'w': /* warning time threshold */ + get_threshold(optarg, wload); break; - case 'c': /* critical time threshold */ - if (is_intnonneg (optarg)) { - cload1 = atof (optarg); - cload5 = atof (optarg); - cload15 = atof (optarg); - break; - } - else if (strstr (optarg, ",") && - sscanf (optarg, "%f,%f,%f", &cload1, &cload5, &cload15) == 3) - break; - else if (strstr (optarg, ":") && - sscanf (optarg, "%f:%f:%f", &cload1, &cload5, &cload15) == 3) - break; - else - usage (_("Critical threshold must be float or float triplet!\n")); + case 'c': /* critical time threshold */ + get_threshold(optarg, cload); + break; + case 'r': /* Divide load average by number of CPUs */ + take_into_account_cpus = 1; break; case 'V': /* version */ - print_revision (progname, "$Revision$"); + print_revision (progname, NP_VERSION); exit (STATE_OK); case 'h': /* help */ print_help (); exit (STATE_OK); case '?': /* help */ - usage (_("Invalid argument\n")); + usage5 (); } } c = optind; if (c == argc) return validate_arguments (); - if (wload1 < 0 && is_nonnegative (argv[c])) - wload1 = atof (argv[c++]); - - if (c == argc) - return validate_arguments (); - if (cload1 < 0 && is_nonnegative (argv[c])) - cload1 = atof (argv[c++]); - - if (c == argc) - return validate_arguments (); - if (wload5 < 0 && is_nonnegative (argv[c])) - wload5 = atof (argv[c++]); - - if (c == argc) - return validate_arguments (); - if (cload5 < 0 && is_nonnegative (argv[c])) - cload5 = atof (argv[c++]); - - if (c == argc) - return validate_arguments (); - if (wload15 < 0 && is_nonnegative (argv[c])) - wload15 = atof (argv[c++]); - if (c == argc) - return validate_arguments (); - if (cload15 < 0 && is_nonnegative (argv[c])) - cload15 = atof (argv[c++]); + /* handle the case if both arguments are missing, + * but not if only one is given without -c or -w flag */ + if(c - argc == 2) { + get_threshold(argv[c++], wload); + get_threshold(argv[c++], cload); + } + else if(c - argc == 1) { + get_threshold(argv[c++], cload); + } return validate_arguments (); } - - -int +static int validate_arguments (void) { - if (wload1 < 0) - usage (_("Warning threshold for 1-minute load average is not specified\n")); - if (wload5 < 0) - usage (_("Warning threshold for 5-minute load average is not specified\n")); - if (wload15 < 0) - usage (_("Warning threshold for 15-minute load average is not specified\n")); - if (cload1 < 0) - usage (_("Critical threshold for 1-minute load average is not specified\n")); - if (cload5 < 0) - usage (_("Critical threshold for 5-minute load average is not specified\n")); - if (cload15 < 0) - usage (_("Critical threshold for 15-minute load average is not specified\n")); - if (wload1 > cload1) - usage (_("Parameter inconsistency: 1-minute \"warning load\" greater than \"critical load\".\n")); - if (wload5 > cload5) - usage (_("Parameter inconsistency: 5-minute \"warning load\" greater than \"critical load\".\n")); - if (wload15 > cload15) - usage (_("Parameter inconsistency: 15-minute \"warning load\" greater than \"critical load\".\n")); + int i = 0; + + /* match cload first, as it will give the most friendly error message + * if user hasn't given the -c switch properly */ + for(i = 0; i < 3; i++) { + if(cload[i] < 0) + die (STATE_UNKNOWN, _("Critical threshold for %d-minute load average is not specified\n"), nums[i]); + if(wload[i] < 0) + die (STATE_UNKNOWN, _("Warning threshold for %d-minute load average is not specified\n"), nums[i]); + if(wload[i] > cload[i]) + die (STATE_UNKNOWN, _("Parameter inconsistency: %d-minute \"warning load\" is greater than \"critical load\"\n"), nums[i]); + } + return OK; } - - - void print_help (void) { - print_revision (progname, revision); + print_revision (progname, NP_VERSION); - printf (_("Copyright (c) 1999 Felipe Gustavo de Almeida \n")); - printf (_(COPYRIGHT), copyright, email); + printf ("Copyright (c) 1999 Felipe Gustavo de Almeida \n"); + printf (COPYRIGHT, copyright, email); - printf (_("This plugin tests the current system load average.\n\n")); + printf (_("This plugin tests the current system load average.")); - print_usage (); + printf ("\n\n"); - printf (_(UT_HELP_VRSN)); + print_usage (); - printf (_("\ - -w, --warning=WLOAD1,WLOAD5,WLOAD15\n\ - Exit with WARNING status if load average exceeds WLOADn\n\ - -c, --critical=CLOAD1,CLOAD5,CLOAD15\n\ - Exit with CRITICAL status if load average exceed CLOADn\n\n\ -the load average format is the same used by \"uptime\" and \"w\"\n\n")); + printf (UT_HELP_VRSN); + printf (UT_EXTRA_OPTS); + + printf (" %s\n", "-w, --warning=WLOAD1,WLOAD5,WLOAD15"); + printf (" %s\n", _("Exit with WARNING status if load average exceeds WLOADn")); + printf (" %s\n", "-c, --critical=CLOAD1,CLOAD5,CLOAD15"); + printf (" %s\n", _("Exit with CRITICAL status if load average exceed CLOADn")); + printf (" %s\n", _("the load average format is the same used by \"uptime\" and \"w\"")); + printf (" %s\n", "-r, --percpu"); + printf (" %s\n", _("Divide the load averages by the number of CPUs (when possible)")); + +#ifdef NP_EXTRA_OPTS + printf ("\n"); + printf ("%s\n", _("Notes:")); + printf (UT_EXTRA_OPTS_NOTES); +#endif - printf (_(UT_SUPPORT)); + printf (UT_SUPPORT); } void print_usage (void) { - printf (_("Usage: %s -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n"), - progname); - printf (_(UT_HLP_VRS), progname, progname); + printf (_("Usage:")); + printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname); }