X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=plugins%2Fcheck_load.c;h=940d37ec9417cf54cc9b31c3acd6ceb93aef09ae;hb=5a6268f72953d7d0aa0f22f278ac929b1f183686;hp=6673b1dcaf55ae0ec6923e507a33e45be417e1a8;hpb=44a321cb8a42d6c0ea2d96a1086a17f2134c89cc;p=nagiosplug.git diff --git a/plugins/check_load.c b/plugins/check_load.c index 6673b1d..940d37e 100644 --- a/plugins/check_load.c +++ b/plugins/check_load.c @@ -1,32 +1,40 @@ -/****************************************************************************** - * - * CHECK_LOAD.C - * - * Written by Felipe Gustavo de Almeida - * License: GPL - * Command line: CHECK_LOAD - * First Written: 04/17/99 - * - * Modifications: - * - * 05/18/1999 - Modified to work getloadavg where available, and use uptime - * where neither proc or getloadavg are found. Also use autoconf. - * mods by Karl DeBisschop (kdebiss@alum.mit.edu) - * 07/01/1999 - Added some #DEFINEs to allow compilation under NetBSD, as - * suggested by Andy Doran. - * mods by Ethan Galstad (nagios@nagios.org) - * 07/17/1999 - Initialized la[] array to prevent NetBSD from complaining - * mods by Ethan Galstad (nagios@nagios.org) - * 08/18/1999 - Integrated some code with common plugin utilities - * mods by Ethan Galstad (nagios@nagios.org) - * $Date$ - * Note: The load format is the same used by "uptime" and "w" - * - *****************************************************************************/ - -#include "config.h" +/***************************************************************************** +* +* 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 *copyright = "1999-2007"; +const char *email = "nagiosplug-devel@lists.sourceforge.net"; + #include "common.h" #include "utils.h" +#include "popen.h" #ifdef HAVE_SYS_LOADAVG_H #include @@ -39,243 +47,243 @@ #define LOADAVG_15MIN 2 #endif /* !defined LOADAVG_1MIN */ -#include "popen.h" -#ifdef HAVE_PROC_LOADAVG -#endif +static int process_arguments (int argc, char **argv); +static int validate_arguments (void); +void print_help (void); +void print_usage (void); -#define PROGNAME "check_load" +/* strictly for pretty-print usage in loops */ +static const int nums[3] = { 1, 5, 15 }; -int process_arguments (int argc, char **argv); -int call_getopt (int argc, char **argv); -int validate_arguments (void); -void print_usage (void); -void print_help (void); +/* 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]; + } +} -float wload1 = -1, wload5 = -1, wload15 = -1; -float cload1 = -1, cload5 = -1, cload15 = -1; 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 */ -#elif 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 ("\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]; -#elif HAVE_PROC_LOADAVG==1 +#else +# ifdef HAVE_PROC_LOADAVG fp = fopen (PROC_LOADAVG, "r"); if (fp == NULL) { - printf ("Error opening %s\n", PROC_LOADAVG); + 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); -#else +# else child_process = spopen (PATH_TO_UPTIME); if (child_process == NULL) { - printf ("Error opening %s\n", PATH_TO_UPTIME); + printf (_("Error opening %s\n"), PATH_TO_UPTIME); return STATE_UNKNOWN; } child_stderr = fdopen (child_stderr_array[fileno (child_process)], "r"); if (child_stderr == NULL) { - printf ("Could not open stderr for %s\n", PATH_TO_UPTIME); + 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) { - printf ("Error code %d returned in %s\n", result, PATH_TO_UPTIME); + printf (_("Error code %d returned in %s\n"), result, PATH_TO_UPTIME); return STATE_UNKNOWN; } +# endif #endif - if ((la1 == -1) || (la5 == -1) || (la15 == -1)) { -#if HAVE_GETLOADAVG==1 - printf ("Error in getloadavg()\n"); -#elif HAVE_PROC_LOADAVG==1 - printf ("Error processing %s\n", PROC_LOADAVG); + 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 - printf ("Error processing %s\n", PATH_TO_UPTIME); +# ifdef HAVE_PROC_LOADAVG + printf (_("Error processing %s\n"), PROC_LOADAVG); +# else + printf (_("Error processing %s\n"), PATH_TO_UPTIME); +# endif #endif return STATE_UNKNOWN; } - printf ("load average: %.2f, %.2f, %.2f", la1, la5, la15); - if ((la1 >= cload1) || (la5 >= cload5) || (la15 >= cload15)) { - printf (" CRITICAL\n"); - return STATE_CRITICAL; - } - if ((la1 >= wload1) || (la5 >= wload5) || (la15 >= wload15)) { - printf (" WARNING\n"); - return STATE_WARNING; - } - printf ("\n"); - return STATE_OK; -} - + /* 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); - -/* process command-line arguments */ -int -process_arguments (int argc, char **argv) -{ - int c; - - if (argc < 2) - return ERROR; - - c = 0; - while (c += (call_getopt (argc - c, &argv[c]))) { - if (argc <= c) + for(i = 0; i < 3; i++) { + if(la[i] > cload[i]) { + result = STATE_CRITICAL; break; - - if (wload1 < 0 && is_nonnegative (argv[c])) - wload1 = atof (argv[c]); - else if (cload1 < 0 && is_nonnegative (argv[c])) - cload1 = atof (argv[c]); - else if (wload5 < 0 && is_nonnegative (argv[c])) - wload5 = atof (argv[c]); - else if (cload5 < 0 && is_nonnegative (argv[c])) - cload5 = atof (argv[c]); - else if (wload15 < 0 && is_nonnegative (argv[c])) - wload15 = atof (argv[c]); - else if (cload15 < 0 && is_nonnegative (argv[c])) - cload15 = atof (argv[c]); + } + else if(la[i] > wload[i]) result = STATE_WARNING; } - return validate_arguments (); -} - - + 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; +} -int -call_getopt (int argc, char **argv) +/* process command-line arguments */ +static int +process_arguments (int argc, char **argv) { - int c, i = 0; + int c = 0; -#ifdef HAVE_GETOPT_H - int option_index = 0; - static struct option long_options[] = { + int option = 0; + 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} }; -#endif - while (1) { -#ifdef HAVE_GETOPT_H - c = getopt_long (argc, argv, "+?Vhc:w:", long_options, &option_index); -#else - c = getopt (argc, argv, "+?Vhc:w:"); -#endif + if (argc < 2) + return ERROR; - i++; + while (1) { + c = getopt_long (argc, argv, "Vhrc:w:", longopts, &option); if (c == -1 || c == EOF) break; switch (c) { - case 'c': - case 'w': - i++; - } - - switch (c) { - case 'w': /* warning time threshold */ - if (is_intnonneg (optarg)) { - if (wload1 < 0 && is_nonnegative (argv[c])) - wload1 = atof (argv[c]); - else if (wload5 < 0 && is_nonnegative (argv[c])) - wload5 = atof (argv[c]); - else if (wload15 < 0 && is_nonnegative (argv[c])) - wload15 = atof (argv[c]); - 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 'c': /* critical time threshold */ - if (is_intnonneg (optarg)) { - if (cload1 < 0 && is_nonnegative (argv[c])) - cload1 = atof (argv[c]); - else if (cload5 < 0 && is_nonnegative (argv[c])) - cload5 = atof (argv[c]); - else if (cload15 < 0 && is_nonnegative (argv[c])) - cload15 = atof (argv[c]); - 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 'w': /* warning time threshold */ + get_threshold(optarg, wload); + break; + 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 (my_basename (argv[0]), "$Revision$"); + print_revision (progname, NP_VERSION); exit (STATE_OK); case 'h': /* help */ print_help (); exit (STATE_OK); case '?': /* help */ - usage ("Invalid argument\n"); + usage5 (); } } - return i; -} + c = optind; + if (c == argc) + return validate_arguments (); + /* 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 > cload1) || (wload5 > cload5) || (wload15 > cload15)) { - printf - ("Inconsistence in parameters: \"warning load\" greater than \"critical load\".\n"); - return STATE_UNKNOWN; + 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; @@ -283,39 +291,43 @@ validate_arguments (void) - - void -print_usage (void) +print_help (void) { - printf - ("Usage: check_load -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n" - " check_load --version\n" " check_load --help\n"); -} + print_revision (progname, NP_VERSION); + printf ("Copyright (c) 1999 Felipe Gustavo de Almeida \n"); + printf (COPYRIGHT, copyright, email); + printf (_("This plugin tests the current system load average.")); + printf ("\n\n"); + print_usage (); + + 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)); +} void -print_help (void) +print_usage (void) { - print_revision (PROGNAME, "$Revision$"); - printf - ("Copyright (c) 1999 Felipe Gustavo de Almeida \n" - "Copyright (c) 2000 Karl DeBisschop\n\n" - "This plugin tests the current system load average.\n\n"); - print_usage (); - printf - ("\nOptions:\n" - " -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" - " -h, --help\n" - " Print detailed help screen\n" - " -V, --version\n" - " Print version information\n\n" - "the load average format is the same used by \"uptime\" and \"w\"\n\n"); - support (); + printf (_("Usage:")); + printf ("%s [-r] -w WLOAD1,WLOAD5,WLOAD15 -c CLOAD1,CLOAD5,CLOAD15\n", progname); }