#!/bin/bash : << =cut =head1 NAME ipmi_ - Plugin to monitor temperature, fan speed, watts or volts using IPMI =head1 CONFIGURATION =head2 ENVIRONMENT VARIABLES This plugin does not use environment variables =head2 WILDCARD PLUGIN This plugin should be linked as ipmi_temp, ipmi_fans, ipmi_power or ipmi_volts, and will show either temperatures, fan speeds, watts or volts based on its link name. =head1 NOTE WARNING: Munin has a 10 second default timeout on plugins. On some hosts ipmitool takes longer than that to probe all your hardware. In this case this plugin us unusable. =head1 AUTHOR Nicolai Langfeldt =head1 LICENSE Donated to the public domain by Nicolai Langfeldt (janl@linpro.no) =head1 MAGIC MARKERS #%# family=auto #%# capabilities=autoconf suggest =cut #### Parse commandline to determine what the job is CONFIG=no autoconf() { type -p ipmitool &>/dev/null || { echo 'no (missing ipmitool command)' && return 1; } ipmitool sensor &>/dev/null || { echo 'no (unable to access IPMI device)' && return 1; } return 0 } case $1 in autoconf) autoconf || exit 0; echo yes exit 0 ;; suggest) autoconf > /dev/null || exit 0 echo fans echo temp echo power echo volts exit 0;; config) CONFIG=config;; esac case $0 in *_temp) MEASURE=temp;; *_fans) MEASURE=fans;; *_power) MEASURE=power;; *_volts) MEASURE=volts;; *) echo "Please invoke as ipmi_temp, ipmi_fans, ipmi_power or ipmi_volts" >&2 exit 1;; esac export CONFIG MEASURE #### Work is done in this awk script ipmitool sensor | gawk -F'|' ' BEGIN { FANS = ""; TEMPS = ""; POWER = ""; VOLTS = ""; CFANS = "graph_title Fan speeds based on IPMI\ngraph_vlabel RPM or %\ngraph_category Sensors\n"; CTEMPS = "graph_title Machine temperature based on IPMI\ngraph_vlabel Degrees celsius\ngraph_category Sensors\n"; CPOWER = "graph_title Power usage based on IPMI\ngraph_vlabel W\ngraph_category Sensors\n"; CVOLTS = "graph_title Volts based on IPMI\ngraph_vlabel V\ngraph_category Sensors\n"; } # Remove extraneous spaces to make output prettyer { gsub(/\t/," "); gsub(/ +/," "); gsub(/ +\|/,"|"); gsub(/\| +/,"|") } # Skip lines with 0x0 in first column /^[^|]+\|0x0\|/ { next; }; # Skip lines with na in first column /^[^|]+\|na\|/ { next; }; # Parse temperatures /degrees C/ { NAME=THING=$1; gsub(/[^A-Za-z0-9]/,"",NAME); TEMP=$2; # Find unique name while (NAMES[NAME] >= 1) { NAME=sprintf("%si",NAME); } NAMES[NAME]=1; WARN=$8; CRIT=$9; TEMPS = sprintf("%s%s.value %s\n",TEMPS,NAME,TEMP); CTEMPS = sprintf("%s%s.label %s\n",CTEMPS,NAME,THING); if (CRIT !~ /na/ && CRIT != /^0.000/) { CTEMPS = sprintf("%s%s.critical 0:%s\n",CTEMPS,NAME,CRIT); } if (WARN !~ /na/ && WARN != /^0.000/) { CTEMPS = sprintf("%s%s.warning 0:%s\n",CTEMPS,NAME,WARN); } } /(RPM|^Fan.*percent)/ { NAME=THING=$1; gsub(/[^A-Za-z0-9]/,"",NAME); SPEED=$2; # Find unique name while (NAMES[NAME] >= 1) { NAME=sprintf("%si",NAME); } NAMES[NAME]=1; FANS = sprintf("%s%s.value %s\n",FANS,NAME,SPEED); CFANS = sprintf("%s%s.label %s\n",CFANS,NAME,THING); OK=$4; MIN=$6; if (MIN !~ /na/) { CFANS = sprintf("%s%s.warning %s:\n",CFANS,NAME,MIN); } } /Watts/ { NAME=THING=$1; gsub(/[^A-Za-z0-9]/,"",NAME); WATTS=$2; # Find unique name while (NAMES[NAME] >= 1) { NAME=sprintf("%si",NAME); } NAMES[NAME]=1; POWER = sprintf("%s%s.value %s\n",POWER,NAME,WATTS); CPOWER = sprintf("%s%s.label %s\n",CPOWER,NAME,THING); } /Volts/ { NAME=THING=$1 gsub(/[^A-Za-z0-9]/,"",NAME); VOLTS_SENSOR=$2; # Find unique name while (NAMES[NAME] >= 1) { NAME=sprintf("%si",NAME); } NAMES[NAME]=1; VOLTS = sprintf("%s%s.value %s\n",VOLTS,NAME,VOLTS_SENSOR); CVOLTS = sprintf("%s%s.label %s\n",CVOLTS,NAME,THING); } END { if (ENVIRON["MEASURE"] == "temp") { VALUE=TEMPS; CONFIG=CTEMPS; } else if (ENVIRON["MEASURE"] == "power") { VALUE=POWER; CONFIG=CPOWER; } else if (ENVIRON["MEASURE"] == "volts") { VALUE=VOLTS; CONFIG=CVOLTS; } else { VALUE=FANS; CONFIG=CFANS; } if (ENVIRON["CONFIG"] == "config") printf "%s",CONFIG; else printf "%s",VALUE; } '