int main (int argc, char **argv) { int c, err; bool verbose, cpu_model, per_cpu_stats; unsigned long len, i, count, delay; char *critical = NULL, *warning = NULL; char *p = NULL, *cpu_progname; nagstatus currstatus, status; thresholds *my_threshold = NULL; float cpu_perc = 0.0; unsigned int tog = 0; /* toggle switch for cleaner code */ struct cpu_desc *cpudesc = NULL; set_program_name (argv[0]); len = strlen (program_name); if (len > 6 && !strncmp (program_name, "check_", 6)) p = (char *) program_name + 6; else plugin_error (STATE_UNKNOWN, 0, "bug: the plugin does not have a standard name"); if (!strncmp (p, "iowait", 6)) /* check_iowait --> cpu_iowait */ { cpu_progname = xstrdup ("iowait"); program_shorthelp = xstrdup ("This plugin checks I/O wait bottlenecks\n"); } else /* check_cpu --> cpu_user (the default) */ { cpu_progname = xstrdup ("user");; program_shorthelp = xstrdup ("This plugin checks the CPU (user mode) utilization\n"); } err = cpu_desc_new (&cpudesc); if (err < 0) plugin_error (STATE_UNKNOWN, err, "memory exhausted"); /* default values */ verbose = per_cpu_stats = false; cpu_model = true; while ((c = getopt_long ( argc, argv, "c:w:vifmp" GETOPT_HELP_VERSION_STRING, longopts, NULL)) != -1) { switch (c) { default: usage (stderr); case 'i': cpu_desc_read (cpudesc); cpu_desc_summary (cpudesc); return STATE_UNKNOWN; case 'm': cpu_model = false; break; case 'p': per_cpu_stats = true; break; case 'c': critical = optarg; break; case 'w': warning = optarg; break; case 'v': verbose = true; break; case_GETOPT_HELP_CHAR case_GETOPT_VERSION_CHAR } } delay = DELAY_DEFAULT, count = COUNT_DEFAULT; if (optind < argc) { delay = strtol_or_err (argv[optind++], "failed to parse argument"); if (delay < 1) plugin_error (STATE_UNKNOWN, 0, "delay must be positive integer"); else if (DELAY_MAX < delay) plugin_error (STATE_UNKNOWN, 0, "too large delay value (greater than %d)", DELAY_MAX); } if (optind < argc) { count = strtol_or_err (argv[optind++], "failed to parse argument"); if (COUNT_MAX < count) plugin_error (STATE_UNKNOWN, 0, "too large count value (greater than %d)", COUNT_MAX); } status = set_thresholds (&my_threshold, warning, critical); if (status == NP_RANGE_UNPARSEABLE) usage (stderr); int ncpus = per_cpu_stats ? get_processor_number_total () + 1 : 1; jiff duser[ncpus], dsystem[ncpus], didle[ncpus], diowait[ncpus], dsteal[ncpus], ratio[ncpus]; int debt[ncpus]; /* handle idle ticks running backwards */ struct cpu_time cpuv[2][ncpus]; jiff *cpu_value = strncmp (p, "iowait", 6) ? duser : diowait; const char *cpuname; cpu_stats_get_time (cpuv[0], ncpus); for (c = 0; c < ncpus; c++) { duser[c] = cpuv[0][c].user + cpuv[0][c].nice; dsystem[c] = cpuv[0][c].system + cpuv[0][c].irq + cpuv[0][c].softirq; didle[c] = cpuv[0][c].idle; diowait[c] = cpuv[0][c].iowait; dsteal[c] = cpuv[0][c].steal; debt[c] = 0; ratio[c] = duser[c] + dsystem[c] + didle[c] + diowait[c] + dsteal[c]; if (!ratio[c]) ratio[c] = 1, didle[c] = 1; } for (i = 1; i < count; i++) { sleep (delay); tog = !tog; cpu_stats_get_time (cpuv[tog], ncpus); for (c = 0; c < ncpus; c++) { duser[c] = cpuv[tog][c].user - cpuv[!tog][c].user + cpuv[tog][c].nice - cpuv[!tog][c].nice; dsystem[c] = cpuv[tog][c].system - cpuv[!tog][c].system + cpuv[tog][c].irq - cpuv[!tog][c].irq + cpuv[tog][c].softirq - cpuv[!tog][c].softirq; didle[c] = cpuv[tog][c].idle - cpuv[!tog][c].idle; diowait[c] = cpuv[tog][c].iowait - cpuv[!tog][c].iowait; dsteal[c] = cpuv[tog][c].steal - cpuv[!tog][c].steal; /* idle can run backwards for a moment -- kernel "feature" */ if (debt[c]) { didle[c] = (int) didle[c] + debt[c]; debt[c] = 0; } if ((int) didle[c] < 0) { debt[c] = (int) didle[c]; didle[c] = 0; } ratio[c] = duser[c] + dsystem[c] + didle[c] + diowait[c] + dsteal[c]; if (!ratio[c]) ratio[c] = 1, didle[c] = 1; if (NULL == (cpuname = cpuv[0][c].cpuname)) cpuname = "n/a"; if (verbose) printf ("%s_user=%.1f%%, %s_system=%.1f%%, %s_idle=%.1f%%, " "%s_iowait=%.1f%%, %s_steal=%.1f%%\n" , cpuname, 100.0 * duser[c] / ratio[c] , cpuname, 100.0 * dsystem[c] / ratio[c] , cpuname, 100.0 * didle[c] / ratio[c] , cpuname, 100.0 * diowait[c] / ratio[c] , cpuname, 100.0 * dsteal[c] / ratio[c]); dbg ("sum (%s_*) = %.1f%%\n", cpuname, (100.0 * duser[c] / ratio[c]) + (100.0 * dsystem[c] / ratio[c]) + (100.0 * didle[c] / ratio[c]) + (100.0 * diowait[c] / ratio[c]) + (100.0 * dsteal[c] / ratio[c])); } } for (c = 0, status = STATE_OK; c < ncpus; c++) { cpu_perc = (100.0 * (cpu_value[c]) / ratio[c]); currstatus = get_status (cpu_perc, my_threshold); if (currstatus > status) status = currstatus; } cpu_desc_read (cpudesc); char *cpu_model_str = cpu_model ? xasprintf ("(%s) ", cpu_desc_get_model_name (cpudesc)) : NULL; printf ("%s %s%s - cpu %s %.1f%% |" , program_name_short, cpu_model ? cpu_model_str : "" , state_text (status), cpu_progname, cpu_perc); for (c = 0; c < ncpus; c++) { if ((cpuname = cpuv[0][c].cpuname)) printf (" %s_user=%.1f%% %s_system=%.1f%% %s_idle=%.1f%%" " %s_iowait=%.1f%% %s_steal=%.1f%%" , cpuname, 100.0 * duser[c] / ratio[c] , cpuname, 100.0 * dsystem[c] / ratio[c] , cpuname, 100.0 * didle[c] / ratio[c] , cpuname, 100.0 * diowait[c] / ratio[c] , cpuname, 100.0 * dsteal[c] / ratio[c]); } putchar ('\n'); cpu_desc_unref (cpudesc); return status; }
void cpu_desc_read (struct cpu_desc *cpudesc) { char *line = NULL, *buf; FILE *fp; size_t len = 0; ssize_t chread; struct utsname utsbuf; if (cpudesc == NULL) return; if ((fp = fopen (PATH_PROC_CPUINFO, "r")) == NULL) plugin_error (STATE_UNKNOWN, errno, "error opening %s", PATH_PROC_CPUINFO); if (uname (&utsbuf) == -1) plugin_error (STATE_UNKNOWN, errno, "uname() failed"); cpudesc->arch = xstrdup (utsbuf.machine); cpudesc->ncpus = get_processor_number_total (); cpudesc->ncpuspos = get_processor_number_kernel_max (); cpudesc->mode = 0; #if defined(__alpha__) || defined(__ia64__) cpudesc->mode |= MODE_64BIT; /* 64bit platforms only */ #endif /* platforms with 64bit flag in /proc/cpuinfo, define * 32bit default here */ #if defined(__i386__) || defined(__x86_64__) || \ defined(__s390x__) || defined(__s390__) || defined(__sparc_v9__) cpudesc->mode |= MODE_32BIT; #endif while ((chread = getline (&line, &len, fp)) != -1) { if (linelookup (line, "vendor", &cpudesc->vendor)); else if (linelookup (line, "vendor_id", &cpudesc->vendor)); else if (linelookup (line, "family", &cpudesc->family)); else if (linelookup (line, "cpu family", &cpudesc->family)); else if (linelookup (line, "model", &cpudesc->model)); else if (linelookup (line, "model name", &cpudesc->modelname)) ; else if (linelookup (line, "cpu MHz", &cpudesc->mhz)) ; else if (linelookup (line, "flags", &cpudesc->flags)) ; /* x86 */ else continue; } if (cpudesc->flags) { size_t buflen = strlen (cpudesc->flags) + 2; buf = xmalloc (buflen); snprintf (buf, buflen, " %s ", cpudesc->flags); if (strstr (buf, " svm ")) cpudesc->virtflag = xstrdup ("svm"); else if (strstr (buf, " vmx ")) cpudesc->virtflag = xstrdup ("vmx"); if (strstr (buf, " lm ")) cpudesc->mode |= MODE_32BIT | MODE_64BIT; /* x86_64 */ if (strstr (buf, " zarch ")) cpudesc->mode |= MODE_32BIT | MODE_64BIT; /* s390x */ if (strstr (buf, " sun4v ") || strstr (buf, " sun4u ")) cpudesc->mode |= MODE_32BIT | MODE_64BIT; /* sparc64 */ free (buf); } free (line); }