#!/bin/sh # # Simple Bourne Shell script that implements Munin protocoll and # some common Linux plugins. # # For latest version, see http://muninlite.sf.net/ # # Copyright (c) 2007-2011 Rune Nordbøe Skillingstad # # Licensed under GPLv2 (see LICENSE file for full License) # # $Id: $ # VERSION="1.0.4" NTP_PEER="pool.ntp.org"; # if plugindir_ is present in $PLUGINS, # iexecutables (scripts, binaries) matching the following pattern will be scanned and operated as plugins PLUGINPATTERN=$(dirname $0)"/munin-node-plugin.d/*" # Remove unwanted plugins from this list PLUGINS="df cpu if_ if_err_ load memory processes swap netstat uptime interrupts irqstats ntpdate plugindir_" # ===== LIB FUNCTIONS ===== clean_fieldname() { echo "$@" | sed -e 's/^[^A-Za-z_]/_/' -e 's/[^A-Za-z0-9_]/_/g' } # ===== PLUGINS CODE ===== config_df() { echo "graph_title Filesystem usage (in %) graph_args --upper-limit 100 -l 0 graph_vlabel % graph_category disk graph_info This graph shows disk usage on the machine." for PART in $(df -P | grep '^/' | sed '/\/[a-z0-9]*$/!d;s/.* \([a-z0-9\/]\{1,\}\)$//g') do PINFO=$(df -P $PART | tail -1); PNAME=$(echo $PINFO | cut -d\ -f1 | sed 's/\//_/g') echo "$PNAME.label $PART" echo "$PNAME.info $PNAME -> $PART" echo "$PNAME.warning 92" echo "$PNAME.critical 98" done } fetch_df() { for PART in $(df -P | grep '^/' | sed '/\/[a-z0-9]*$/!d;s/.* \([a-z0-9\/]\{1,\}\)$//g') do PINFO=$(df -P $PART | tail -1); PNAME=$(echo $PINFO | cut -d\ -f1 | sed 's/[\/.-]/_/g') echo "$PNAME.value" $(echo $PINFO | cut -f5 -d\ | sed -e 's/\%//g') done } config_cpu() { extinfo="" if grep '^cpu \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\}' /proc/stat >/dev/null 2>&1; then extinfo="iowait irq softirq" fi NCPU=$(($(grep '^cpu. ' /proc/stat | wc -l) - 1)) if [ $NCPU = 0 ]; then NCPU=1; fi PERCENT=$(($NCPU * 100)) graphlimit=$PERCENT SYSWARNING=$(($PERCENT * 30 / 100)) SYSCRITICAL=$(($PERCENT * 50 / 100)) USRWARNING=$(($PERCENT * 80 / 100)) echo "graph_title CPU usage" echo "graph_order system user nice idle" $extinfo echo "graph_args --base 1000 -r --lower-limit 0 --upper-limit $graphlimit" echo "graph_vlabel %" echo "graph_scale no" echo "graph_info This graph shows how CPU time is spent." echo "graph_category system" echo "graph_period second" echo "system.label system" echo "system.draw AREA" echo "system.max 5000" echo "system.min 0" echo "system.type DERIVE" echo "system.warning $SYSWARNING" echo "system.critical $SYSCRITICAL" echo "system.info CPU time spent by the kernel in system activities" echo "user.label user" echo "user.draw STACK" echo "user.min 0" echo "user.max 5000" echo "user.warning $USRWARNING" echo "user.type DERIVE" echo "user.info CPU time spent by normal programs and daemons" echo "nice.label nice" echo "nice.draw STACK" echo "nice.min 0" echo "nice.max 5000" echo "nice.type DERIVE" echo "nice.info CPU time spent by nice(1)d programs" echo "idle.label idle" echo "idle.draw STACK" echo "idle.min 0" echo "idle.max 5000" echo "idle.type DERIVE" echo "idle.info Idle CPU time" if [ ! -z "$extinfo" ]; then echo "iowait.label iowait" echo "iowait.draw STACK" echo "iowait.min 0" echo "iowait.max 5000" echo "iowait.type DERIVE" echo "iowait.info CPU time spent waiting for I/O operations to finish" echo "irq.label irq" echo "irq.draw STACK" echo "irq.min 0" echo "irq.max 5000" echo "irq.type DERIVE" echo "irq.info CPU time spent handling interrupts" echo "softirq.label softirq" echo "softirq.draw STACK" echo "softirq.min 0" echo "softirq.max 5000" echo "softirq.type DERIVE" echo "softirq.info CPU time spent handling "batched" interrupts" fi } fetch_cpu() { extinfo="" if grep '^cpu \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\} \{1,\}[0-9]\{1,\}' /proc/stat >/dev/null 2>&1; then extinfo="iowait irq softirq" fi CINFO=$(grep '^cpu ' /proc/stat | cut -c6-) echo "user.value" $(echo "$CINFO" | cut -d\ -f1) echo "nice.value" $(echo "$CINFO" | cut -d\ -f2) echo "system.value" $(echo "$CINFO" | cut -d\ -f3) echo "idle.value" $(echo "$CINFO" | cut -d\ -f4) if [ ! -z "$extinfo" ]; then echo "iowait.value" $(echo "$CINFO" | cut -d\ -f5) echo "irq.value" $(echo "$CINFO" | cut -d\ -f6) echo "softirq.value" $(echo "$CINFO" | cut -d\ -f7) fi } config_if() { echo "graph_order down up" echo "graph_title $1 traffic" echo "graph_args --base 1000" echo "graph_vlabel bits in (-) / out (+) per \${graph_period}" echo "graph_category network" echo "graph_info This graph shows the traffic of the $INTERFACE network interface. Please note that the traffic is shown in bits per second, not bytes. IMPORTANT: Since the data source for this plugin use 32bit counters, this plugin is really unreliable and unsuitable for most 100Mb (or faster) interfaces, where bursts are expected to exceed 50Mbps. This means that this plugin is usuitable for most production environments. To avoid this problem, use the ip_ plugin instead." echo "down.label received" echo "down.type DERIVE" echo "down.min 0" echo "down.graph no" echo "down.cdef down,8,*" echo "up.label bps" echo "up.type DERIVE" echo "up.min 0" echo "up.negative down" echo "up.cdef up,8,*" if ethtool $1 | grep -q Speed; then MAX=$(($(ethtool $1 | grep Speed | sed -e 's/[[:space:]]\{1,\}/ /g' -e 's/^ //' -e 's/M.*//' | cut -d\ -f2) * 1000000)) echo "up.max $MAX" echo "down.max $MAX" fi } fetch_if() { IINFO=$(grep "$1:" /proc/net/dev | cut -d: -f2 | sed -e 's/ / /g') echo "down.value" $(echo $IINFO | cut -d\ -f1) echo "up.value" $(echo $IINFO | cut -d\ -f9) } config_if_err() { echo "graph_order rcvd trans" echo "graph_title $1 errors" echo "graph_args --base 1000" echo "graph_vlabel packets in (-) / out (+) per \${graph_period}" echo "graph_category network" echo "graph_info This graph shows the amount of errors on the $1 network interface." echo "rcvd.label packets" echo "rcvd.type COUNTER" echo "rcvd.graph no" echo "rcvd.warning 1" echo "trans.label packets" echo "trans.type COUNTER" echo "trans.negative rcvd" echo "trans.warning 1" } fetch_if_err() { IINFO=$(grep "$1:" /proc/net/dev | cut -d: -f2 | sed -e 's/ / /g') echo "rcvd.value" $(echo $IINFO | cut -d\ -f3) echo "trans.value" $(echo $IINFO | cut -d\ -f11) } config_load() { echo "graph_title Load average graph_args --base 1000 -l 0 graph_vlabel load graph_scale no graph_category system load.label load load.warning 10 load.critical 120 graph_info The load average of the machine describes how many processes are in the run-queue (scheduled to run \"immediately\"). load.info Average load for the five minutes." } fetch_load() { echo "load.value" $(cut -f2 -d\ /proc/loadavg) } config_memory() { MINFO=$(cat /proc/meminfo | sed 's/ \{1,\}/ /g;') MEMTOTAL=$(echo "$MINFO" | grep "^MemTotal:" | cut -d\ -f2) PAGETABLES=$(echo "$MINFO" | grep "^PageTables:" | cut -d\ -f2) SWAPCACHED=$(echo "$MINFO" | grep "^SwapCached:" | cut -d\ -f2) SWAPTOTAL=$(echo "$MINFO" | grep "^SwapTotal:" | cut -d\ -f2) VMALLOCUSED=$(echo "$MINFO" | grep "^VmallocUsed:" | cut -d\ -f2) SLAB=$(echo "$MINFO" | grep "^Slab:" | cut -d\ -f2) MAPPED=$(echo "$MINFO" | grep "^Mapped:" | cut -d\ -f2) COMMITTEDAS=$(echo "$MINFO" | grep "^Committed_AS:" | cut -d\ -f2) ACTIVE=$(echo "$MINFO" | grep "^Active:" | cut -d\ -f2) INACTIVE=$(echo "$MINFO" | grep "^Inactive:" | cut -d\ -f2) ACTIVEANON=$(echo "$MINFO" | grep "^ActiveAnon:" | cut -d\ -f2) ACTIVECACHE=$(echo "$MINFO" | grep "^ActiveCache:" | cut -d\ -f2) INACTIVE=$(echo "$MINFO" | grep "^Inactive:" | cut -d\ -f2) INACTDIRTY=$(echo "$MINFO" | grep "^Inact_dirty:" | cut -d\ -f2) INACTLAUNDY=$(echo "$MINFO" | grep "^Inact_laundry:" | cut -d\ -f2) INACTCLEAN=$(echo "$MINFO" | grep "^Inact_clean:" | cut -d\ -f2) GRAPH_ORDER="apps"; test "$PAGETABLES" != "" && GRAPH_ORDER="$GRAPH_ORDER page_tables" test "$SWAPCACHED" != "" && GRAPH_ORDER="$GRAPH_ORDER swap_cache" test "$VMALLOCUSED" != "" && GRAPH_ORDER="$GRAPH_ORDER vmalloc_used" test "$SLAB" != "" && GRAPH_ORDER="$GRAPH_ORDER slab" GRAPH_ORDER="$GRAPH_ORDER cached buffers free swap" echo "graph_args --base 1024 -l 0 --vertical-label Bytes --upper-limit $MEMTOTAL" echo "graph_title Memory usage" echo "graph_category system" echo "graph_info This graph shows what the machine uses its memory for." echo "graph_order $GRAPH_ORDER" echo "apps.label apps" echo "apps.draw AREA" echo "apps.info Memory used by user-space applications." echo "buffers.label buffers" echo "buffers.draw STACK" echo "buffers.info Block device (e.g. harddisk) cache. Also where \"dirty\" blocks are stored until written." echo "swap.label swap" echo "swap.draw STACK" echo "swap.info Swap space used." echo "cached.label cache" echo "cached.draw STACK" echo "cached.info Parked file data (file content) cache." echo "free.label unused" echo "free.draw STACK" echo "free.info Wasted memory. Memory that is not used for anything at all." if [ "$SLAB" != "" ]; then echo "slab.label slab_cache" echo "slab.draw STACK" echo "slab.info Memory used by the kernel (major users are caches like inode, dentry, etc)." fi if [ "$SWAPCACHED" != "" ]; then echo "swap_cache.label swap_cache" echo "swap_cache.draw STACK" echo "swap_cache.info A piece of memory that keeps track of pages that have been fetched from swap but not yet been modified." fi if [ "$PAGETABLES" != "" ]; then echo "page_tables.label page_tables" echo "page_tables.draw STACK" echo "page_tables.info Memory used to map between virtual and physical memory addresses. " fi if [ "$VMALLOCUSED" != "" ]; then echo "vmalloc_used.label vmalloc_used" echo "vmalloc_used.draw STACK" echo "vmalloc_used.info Virtual memory used by the kernel (used when the memory does not have to be physically contigious)." fi if [ "$COMMITTEDAS" != "" ]; then echo "committed.label committed" echo "committed.draw LINE2" echo "committed.warn" $(($SWAPTOTAL + $MEMTOTAL)) echo "committed.info The amount of memory that would be used if all the memory that's been allocated were to be used." fi if [ "$MAPPED" != "" ]; then echo "mapped.label mapped" echo "mapped.draw LINE2" echo "mapped.info All mmap()ed pages." fi if [ "$ACTIVE" != "" ]; then echo "active.label active" echo "active.draw LINE2" echo "active.info Memory recently used. Not reclaimed unless absolutely necessary." fi if [ "$ACTIVEANON" != "" ]; then echo "active_anon.label active_anon" echo "active_anon.draw LINE1" fi if [ "$ACTIVECACHE" != "" ]; then echo "active_cache.label active_cache" echo "active_cache.draw LINE1" fi if [ "$INACTIVE" != "" ]; then echo "inactive.label inactive" echo "inactive.draw LINE2" echo "inactive.info Memory not currently used." fi if [ "$INACTDIRTY" != "" ]; then echo "inact_dirty.label inactive_dirty" echo "inact_dirty.draw LINE1" echo "inact_dirty.info Memory not currently used, but in need of being written to disk." fi if [ "$INACTLAUNDRY" != "" ]; then echo "inact_laundry.label inactive_laundry" echo "inact_laundry.draw LINE1" fi if [ "$INACTCLEAN" != "" ]; then echo "inact_clean.label inactive_clean" echo "inact_clean.draw LINE1" echo "inact_clean.info Memory not currently used." fi } fetch_memory() { MINFO=$(cat /proc/meminfo | sed 's/ \{1,\}/ /g;') MEMTOTAL=$(echo "$MINFO" | grep "^MemTotal:" | cut -d\ -f2) MEMFREE=$(echo "$MINFO" | grep "^MemFree:" | cut -d\ -f2) BUFFERS=$(echo "$MINFO" | grep "^Buffers:" | cut -d\ -f2) CACHED=$(echo "$MINFO" | grep "^Cached:" | cut -d\ -f2) SWAP_TOTAL=$(echo "$MINFO" | grep "^SwapTotal:" | cut -d\ -f2) SWAP_FREE=$(echo "$MINFO" | grep "^SwapFree:" | cut -d\ -f2) MEMTOTAL=$(echo "$MINFO" | grep "^MemTotal:" | cut -d\ -f2) PAGETABLES=$(echo "$MINFO" | grep "^PageTables:" | cut -d\ -f2) SWAPCACHED=$(echo "$MINFO" | grep "^SwapCached:" | cut -d\ -f2) VMALLOCUSED=$(echo "$MINFO" | grep "^VmallocUsed:" | cut -d\ -f2) SLAB=$(echo "$MINFO" | grep "^Slab:" | cut -d\ -f2) MAPPED=$(echo "$MINFO" | grep "^Mapped:" | cut -d\ -f2) COMMITTEDAS=$(echo "$MINFO" | grep "^Committed_AS:" | cut -d\ -f2) ACTIVE=$(echo "$MINFO" | grep "^Active:" | cut -d\ -f2) INACTIVE=$(echo "$MINFO" | grep "^Inactive:" | cut -d\ -f2) ACTIVEANON=$(echo "$MINFO" | grep "^ActiveAnon:" | cut -d\ -f2) ACTIVECACHE=$(echo "$MINFO" | grep "^ActiveCache:" | cut -d\ -f2) INACTIVE=$(echo "$MINFO" | grep "^Inactive:" | cut -d\ -f2) INACTDIRTY=$(echo "$MINFO" | grep "^Inact_dirty:" | cut -d\ -f2) INACTLAUNDY=$(echo "$MINFO" | grep "^Inact_laundry:" | cut -d\ -f2) INACTCLEAN=$(echo "$MINFO" | grep "^Inact_clean:" | cut -d\ -f2) APPS=$(($MEMTOTAL - $MEMFREE - $BUFFERS - $CACHED)) SWAP=$(($SWAP_TOTAL - $SWAP_FREE)) echo "buffers.value" $(($BUFFERS * 1024)) echo "swap.value" $(($SWAP * 1024)) echo "cached.value" $(($CACHED * 1024)) echo "free.value" $(($MEMFREE * 1024)) if [ "$SLAB" != "" ]; then echo "slab.value" $(($SLAB * 1024)) APPS=$(($APPS - $SLAB)) fi if [ "$SWAPCACHED" != "" ]; then echo "swap_cache.value" $(($SWAPCACHED * 1024)) APPS=$(($APPS - $SWAPCACHED)) fi if [ "$PAGETABLES" != "" ]; then echo "page_tables.value" $(($PAGETABLES * 1024)) APPS=$(($APPS - $PAGETABLES)) fi if [ "$VMALLOCUSED" != "" ]; then echo "vmalloc_used.value" $(($VMALLOCUSED * 1024)) APPS=$(($APPS - $VMALLOCUSED)) fi if [ "$COMMITTEDAS" != "" ]; then echo "committed.value" $(($COMMITTEDAS * 1024)) fi if [ "$MAPPED" != "" ]; then echo "mapped.value" $(($MAPPED * 1024)) fi if [ "$ACTIVE" != "" ]; then echo "active.value" $(($ACTIVE * 1024)) fi if [ "$ACTIVEANON" != "" ]; then echo "active_anon.value" $(($ACTIVEANON * 1024)) fi if [ "$ACTIVECACHE" != "" ]; then echo "active_cache.value" $(($ACTIVECACHE * 1024)) fi if [ "$INACTIVE" != "" ]; then echo "inactive.value" $(($INACTIVE * 1024)) fi if [ "$INACTDIRTY" != "" ]; then echo "inact_dirty.value" $(($INACTDIRTY * 1024)) fi if [ "$INACTLAUNDRY" != "" ]; then echo "inact_laundry.value" $(($INACTLAUNDRY * 1024)) fi if [ "$INACTCLEAN" != "" ]; then echo "inact_clean.value" $(($INACTCLEAN * 1024)) fi echo "apps.value" $(($APPS * 1024)) } config_processes() { echo "graph_title Number of Processes" echo "graph_args --base 1000 -l 0 " echo "graph_vlabel number of processes" echo "graph_category processes" echo "graph_info This graph shows the number of processes in the system." echo "processes.label processes" echo "processes.draw LINE2" echo "processes.info The current number of processes." } fetch_processes() { echo "processes.value" $(echo /proc/[0-9]* | wc -w) } config_swap() { echo "graph_title Swap in/out" echo "graph_args -l 0 --base 1000" echo "graph_vlabel pages per \${graph_period} in (-) / out (+)" echo "graph_category system" echo "swap_in.label swap" echo "swap_in.type DERIVE" echo "swap_in.max 100000" echo "swap_in.min 0" echo "swap_in.graph no" echo "swap_out.label swap" echo "swap_out.type DERIVE" echo "swap_out.max 100000" echo "swap_out.min 0" echo "swap_out.negative swap_in" } fetch_swap() { if [ -f /proc/vmstat ]; then SINFO=$(cat /proc/vmstat) echo "swap_in.value" $(echo "$SINFO" | grep "^pswpin" | cut -d\ -f2) echo "swap_out.value" $(echo "$SINFO" | grep "^pswpout" | cut -d\ -f2) else SINFO=$(grep "^swap" /proc/stat) echo "swap_in.value" $(echo "$SINFO" | cut -d\ -f2) echo "swap_out.value" $(echo "$SINFO" | cut -d\ -f3) fi } config_netstat() { echo "graph_title Netstat" echo "graph_args -l 0 --base 1000" echo "graph_vlabel active connections" echo "graph_category network" echo "graph_period second" echo "graph_info This graph shows the TCP activity of all the network interfaces combined." echo "active.label active" echo "active.type DERIVE" echo "active.max 50000" echo "active.min 0" echo "active.info The number of active TCP openings per second." echo "passive.label passive" echo "passive.type DERIVE" echo "passive.max 50000" echo "passive.min 0" echo "passive.info The number of passive TCP openings per second." echo "failed.label failed" echo "failed.type DERIVE" echo "failed.max 50000" echo "failed.min 0" echo "failed.info The number of failed TCP connection attempts per second." echo "resets.label resets" echo "resets.type DERIVE" echo "resets.max 50000" echo "resets.min 0" echo "resets.info The number of TCP connection resets." echo "established.label established" echo "established.type GAUGE" echo "established.max 50000" echo "established.info The number of currently open connections." } fetch_netstat() { NINFO=$(netstat -s | sed 's/ \{1,\}/ /g') echo "active.value" $(echo "$NINFO" | grep "active connections" | cut -d\ -f2) echo "passive.value" $(echo "$NINFO" | grep "passive connection" | cut -d\ -f2) echo "failed.value" $(echo "$NINFO" | grep "failed connection" | cut -d\ -f2) echo "resets.value" $(echo "$NINFO" | grep "connection resets" | cut -d\ -f2) echo "established.value" $(echo "$NINFO" | grep "connections established" | cut -d\ -f2) } config_uptime() { echo "graph_title Uptime" echo "graph_args --base 1000 -l 0 " echo "graph_vlabel uptime in days" echo "uptime.label uptime" echo "uptime.draw AREA" echo "uptime.cdef uptime,86400,/" } fetch_uptime() { echo "uptime.value" $(cut -d\ -f1 /proc/uptime) } config_interrupts() { echo "graph_title Interrupts & context switches" echo "graph_args --base 1000 -l 0" echo "graph_vlabel interrupts & ctx switches / \${graph_period}" echo "graph_category system" echo "graph_info This graph shows the number of interrupts and context switches on the system. These are typically high on a busy system." echo "intr.info Interrupts are events that alter sequence of instructions executed by a processor. They can come from either hardware (exceptions, NMI, IRQ) or software." echo "ctx.info A context switch occurs when a multitasking operatings system suspends the currently running process, and starts executing another." echo "intr.label interrupts" echo "ctx.label context switches" echo "intr.type DERIVE" echo "ctx.type DERIVE" echo "intr.max 100000" echo "ctx.max 100000" echo "intr.min 0" echo "ctx.min 0" } fetch_interrupts() { IINFO=$(cat /proc/stat) echo "ctx.value" $(echo "$IINFO" | grep "^ctxt" | cut -d\ -f2) echo "intr.value" $(echo "$IINFO" | grep "^intr" | cut -d\ -f2) } config_irqstats() { echo "graph_title Individual interrupts graph_args --base 1000 -l 0; graph_vlabel interrupts / \${graph_period} graph_category system" CPUS=$(grep 'CPU[0-9]' /proc/interrupts | wc -w) IINFO=$(sed -e 's/ \{1,\}/ /g' -e 's/^ //' /proc/interrupts | grep '.:') for ID in $(echo "$IINFO" | cut -d: -f1) do IDL=$(echo "$IINFO" | grep "^$ID:") INFO=$(eval "echo \"$IDL\" | cut -d\ -f$((3+$CPUS))-") if [ "$INFO" = "" ]; then echo "i$ID.label $ID" else echo "i$ID.label $INFO" echo "i$ID.info Interrupt $ID, for device(s): $INFO" fi echo "i$ID.type DERIVE" echo "i$ID.min 0" done } fetch_irqstats() { CPUS=$(grep 'CPU[0-9]' /proc/interrupts | wc -w) IINFO=$(sed -e 's/ \{1,\}/ /g' -e 's/^ //' /proc/interrupts | grep '.:') for ID in $(echo "$IINFO" | cut -d: -f1) do IDL=$(echo "$IINFO" | grep "^$ID:") VALS=$(eval "echo \"$IDL\" | cut -d\ -f2-$((1+$CPUS))") VALUE=0 for VAL in $VALS; do VALUE=$(($VALUE + $VAL)) done echo "i$ID.value $VALUE" done } config_ntpdate() { echo "graph_title NTP offset and dealy to peer $NTP_PEER" echo "graph_args --base 1000 --vertical-label msec" echo "offset.label Offset" echo "offset.draw LINE2" echo "delay.label Delay" echo "delay.draw LINE2" } fetch_ntpdate() { NTPDATE="/usr/sbin/ntpdate" OFFSET=0 DELAY=0 if [ "$NTP_PEER" != "" ]; then if [ -x "$NTPDATE" ]; then DATA=$($NTPDATE -q $NTP_PEER | awk '/^server.*offset/{gsub(/,/,"");printf "%s %s", ($6*1000), ($8*1000);}') OFFSET=$(echo "$DATA" | cut -d\ -f1) DELAY=$(echo "$DATA" | cut -d\ -f2) fi fi echo "offset.value $OFFSET" echo "delay.value $DELAY" } # ===== NODE CODE ===== do_list() { echo $PLUGINS } do_nodes() { echo "$HOSTNAME" echo "." } do_config() { if echo "$PLUGINS" | grep "\b$1\b" >/dev/null 2>&1; then config_$1 else echo "# Unknown service" fi echo "." } do_fetch() { if echo "$PLUGINS" | grep "\b$1\b" >/dev/null 2>&1; then fetch_$1 else echo "# Unknown service" fi echo "." } do_version() { echo "munins node on $HOSTNAME version: $VERSION (munin-lite)" } do_quit() { exit 0 } # ===== Runtime config ===== RES="" for PLUG in $PLUGINS do if [ "$PLUG" = "if_" ]; then for INTER in $(grep '^ *\(ppp\|eth\|wlan\|ath\|ra\|ipsec\)\([^:]\)\{1,\}:' /proc/net/dev | cut -f1 -d: | sed 's/ //g'); do INTERRES=$(echo $INTER | sed 's/\./VLAN/') RES="$RES if_$INTERRES" eval "fetch_if_${INTERRES}() { fetch_if $INTER $@; };" eval "config_if_${INTERRES}() { config_if $INTER $@; };" done elif [ "$PLUG" = "if_err_" ]; then for INTER in $(grep '^ *\(ppp\|eth\|wlan\|ath\|ra\|ipsec\)\([^:]\)\{1,\}:' /proc/net/dev | cut -f1 -d: | sed 's/ //g'); do INTERRES=$(echo $INTER | sed 's/\./VLAN/') RES="$RES if_err_$INTERRES" eval "fetch_if_err_${INTERRES}() { fetch_if_err $INTER $@; };" eval "config_if_err_${INTERRES}() { config_if_err $INTER $@; };" done elif [ "$PLUG" = "netstat" ]; then if netstat -s >/dev/null 2>&1; then RES="$RES netstat" fi elif [ "$PLUG" = "plugindir_" ]; then for MYPLUGIN in $(ls -1 $PLUGINPATTERN 2>/dev/null ); do if [ -f $MYPLUGIN -a -x $MYPLUGIN ]; then MYPLUGINNAME=$(basename $MYPLUGIN) #ensure we don't have name collision if echo "$RES" | grep "\b$MYPLUGINNAME\b" >/dev/null 2>&1 ; then MYPLUGINNAME="plugindir_$MYPLUGINNAME" fi RES="$RES $MYPLUGINNAME" eval "fetch_${MYPLUGINNAME}() { $MYPLUGIN ; };" eval "config_${MYPLUGINNAME}() { $MYPLUGIN config ; };" fi done else RES="$RES $PLUG"; fi done PLUGINS=$RES # ===== MAIN LOOP ===== FUNCTIONS="list nodes config fetch version quit" HOSTNAME=$(hostname -f 2>/dev/null || hostname) echo "# munin node at $HOSTNAME" while read arg0 arg1 do arg0=$(echo "$arg0" | xargs) arg1=$(echo "$arg1" | xargs) if ! echo "$FUNCTIONS" | grep "\b$arg0\b" >/dev/null 2>&1 ; then echo "# Unknown command. Try" $(echo "$FUNCTIONS" | sed -e 's/\( [[:alpha:]]\{1,\}\)/,\1/g' -e 's/,\( [[:alpha:]]\{1,\}\)$/ or\1/') continue fi do_$arg0 $arg1 done