Basierend auf munin-lite habe ich einen munin-node für die Coolstream gebaut. Die jeweils aktuelle Version ist immer hier zu finden.
#!/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 <rune@skillingstad.no> # # Licensed under GPLv2 (see LICENSE file for full License) # # $Id: $ # : <<=cut #################################################################### Angepasste Version fuer das NG-Return-Image der Coolstream von Sven Hoefer <sven@svenhoefer.com> #################################################################### Handhabe: * FTP-Verbindung mit der Coolstream herstellen * diese Datei (munin-node) nach /var/bin kopieren * Telnet-Verbindung mit der Coolstream herstellen * das executable flag setzen: 'chmod +x /var/bin/munin-node' * _einmalig_ '/var/bin/munin-node --prepare' ausfuehren * erster Test mit: 'telnet localhost 4949' * den Munin-Server mit dem neuen Node (Coolstream) bekannt machen: <server>/etc/munin/munin.conf die folgenden Zeilen hinzufuegen: [coolstream.domain] address ip.adresse.der.coolstream use_node_name yes #################################################################### Aenderungen in dieser Version: cst002: * Basiert auf munin-lite 1.0.4 * Plugin "nfs_client" hinzugefuegt * Plugin "cpu" erweitert * Flagfile-Logik geaendert * Funktion "do_prepare()" erweitert * Schalter "--on", "--off" und "--onoff" entfernt. Stattdessen Schalter "start", "stop" und "switch" hinzugefuegt cst001: * Basiert auf munin-lite 1.0.2 * Schalter "--prepare" hinzugefuegt, die die beiden Dateien /etc/services und /etc/inetd.conf prueft bzw. aendert und den inetd neu startet (In /etc/services wird der munin-Port hinzugefuegt und in /etc/inetd.conf wird definiert, dass /var/bin/munin-node gestartet wird, wenn eine Anfrage an den Port gerichtet ist) * Syntaxanpassung an busybox: $((arith)) -> `expr arith` * einige Syntaxkorrekturen * Schalter "--on", "--off" und "--onoff" hinzugefuegt (zur beliebigen Verwendung im Flex-Menue oder in Scripten) #################################################################### =cut # remove unwanted plugins from this list PLUGINS="ng_update df nfs_client cpu memory load processes interrupts irqstats if_ if_err_ uptime" # iexecutables (scripts, binaries) matching the following pattern # will be scanned and operated as plugins. uncomment if wanted #PLUGINPATTERN=$(dirname $0)"/munin-node-plugin.d/*" [ "$PLUGINPATTERN" ] && PLUGINS=$PLUGINS" plugindir_" # ===== VARIOUS VARIABLES ===== HOSTNAME=$(hostname -f 2> /dev/null || hostname) BASENAME=$(basename $0) FULLNAME=$(dirname $0)"/"$BASENAME if [ ! "${FULLNAME:0:1}" = "/" ]; then FULLNAME=$(find / -name "$BASENAME" -xdev) fi # ===== FLAGFILE ===== FLAGDIR="/var/etc" F_MUNIN=".munin-node" # ===== START/STOP FUNCTIONS ===== do_start() { touch $FLAGDIR/$F_MUNIN echo "[$BASENAME] at $HOSTNAME enabled" } do_stop() { rm -f $FLAGDIR/$F_MUNIN echo "[$BASENAME] at $HOSTNAME disabled" } # ===== PREPARATION FUNCTION ===== do_prepare() { done="" if ! grep "4949/tcp" /etc/services > /dev/null; then echo "[$BASENAME] adding munin-stuff to /etc/services" echo -e "\n# munin\nmunin 4949/tcp lrrd # Munin\n" >> /etc/services done="yes" fi if ! grep "$FULLNAME" /etc/inetd.conf > /dev/null; then echo "[$BASENAME] adding munin-stuff to /etc/inetd.conf" echo -e "munin stream tcp nowait root $FULLNAME\n" >> /etc/inetd.conf done="yes" fi if [ "$done" ]; then echo "[$BASENAME] restart inetd" /etc/init.d/inetd restart fi if [ "$PLUGINPATTERN" ] && [ ! -d `dirname $PLUGINPATTERN` ]; then echo "[$BASENAME] creating directory for own plugins" mkdir `dirname $PLUGINPATTERN` fi do_start } # ===== SWITCH QUERY ===== case "$1" in '--prepare') do_prepare exit 0 ;; 'start') do_start exit 0 ;; 'stop') do_stop exit 0 ;; 'switch') if [ -e $FLAGDIR/$F_MUNIN ]; then do_stop else do_start fi exit 0 ;; esac # ===== TO DO OR NOT TO DO ===== if [ ! -e $FLAGDIR/$F_MUNIN ]; then echo "# munins node on $HOSTNAME is disabled. try '$FULLNAME start'" echo "." exit 0 fi # ===== NHTTPD CONFIG ===== # # Vorbereitung fuer Plugins, die auf das yWeb-Interface zugreifen. # Bei Bedarf auskommentieren. # #nhttpc="/var/tuxbox/config/nhttpd.conf" #htauth=`grep "mod_auth.authenticate" $nhttpc | cut -d "=" -f2` #htuser=`grep "mod_auth.username" $nhttpc | cut -d "=" -f2` #htpass=`grep "mod_auth.password" $nhttpc | cut -d "=" -f2` #htport=`grep "WebsiteMain.port" $nhttpc | cut -d "=" -f2` #if [ "$htauth" = "true" ]; then # hturl="http://$htuser:$htpass@127.0.0.1:$htport" #else # hturl="http://127.0.0.1:$htport" #fi # ===== SUBVERSION ===== SUBVER=".cst002" # #################################################################### VERSION="1.0.4$SUBVER" # ===== LIB FUNCTIONS ===== clean_fieldname() { echo "$@" | sed -e 's/^[^A-Za-z_]/_/' -e 's/[^A-Za-z0-9_]/_/g' } # ===== PLUGINS CODE ===== config_ng_update() { [ -e /.version ] && VERSION=$(grep 'version=' /.version | cut -d= -f2) || VERSION=" n/a" echo "graph_title NG-Coolstream Update-Info" echo "graph_args --upper-limit 1 -l 0" echo "graph_vlabel Update" echo "graph_category system" echo "graph_info This graph shows the availability of a new NG-Return Image. Your Version:" ${VERSION:1:3} echo "ng-update.label Availability" echo "ng-update.info Value '1' means 'Yes'" echo "ng-update.warning 0.9" } fetch_ng_update() { VALUE=0 [ -e /.version ] && VERSION=$(grep 'version=' /.version | cut -d= -f2) UPDATE=$(wget -t2 -T2 -q -O- http://wget.biz/release/release.txt 2>/dev/null | grep '.img' | cut -d\ -f2) if [ "$VERSION" ] && [ "$UPDATE" ] && [ "$VERSION" != "$UPDATE" ]; then VALUE=1 fi echo "ng-update.value" $VALUE } config_df() { echo "graph_title Filesystem usage (in %)" echo "graph_args --upper-limit 100 -l 0" echo "graph_vlabel %" echo "graph_category disk" echo "graph_info This graph shows disk usage on the machine." for PART in $(df -P | grep '^mtd\|^/[[:alnum:]]' | sed '/\/[a-z0-9]*$/!d;s/.* \([a-z0-9\/]\{1,\}\)$/\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 '^mtd\|^/[[:alnum:]]' | sed '/\/[a-z0-9]*$/!d;s/.* \([a-z0-9\/]\{1,\}\)$/\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_nfs_client() { NFS=/proc/net/rpc/nfs proc="getattr setattr lookup access readlink read write create mkdir symlink mknod remove rmdir rename link readdir readdirplus fsstat fsinfo pathconf commit" echo 'graph_title NFS Client' echo 'graph_args --base 1000 -l 0' echo 'graph_vlabel requests / ${graph_period}' echo 'graph_total total' echo 'graph_category NFS' for a in $proc do echo "$a.label $a" echo "$a.type DERIVE" echo "$a.min 0" done } fetch_nfs_client() { NFS=/proc/net/rpc/nfs proc="getattr setattr lookup access readlink read write create mkdir symlink mknod remove rmdir rename link readdir readdirplus fsstat fsinfo pathconf commit" awk '/proc3/ { split("'"$proc"'", names) split($0,values) for (e in names) { printf("%s.value %d\n", names[++i], values[i+3]); } }' $NFS } config_cpu() { extinfo="" extextinfo="" 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" 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,\} \{1,\}[0-9]\{1,\}' /proc/stat >/dev/null 2>&1; then extextinfo="steal" fi fi NCPU=`expr $(grep '^cpu. ' /proc/stat | wc -l) - 1` PERCENT=`expr $NCPU \* 100` graphlimit=$PERCENT SYSWARNING=`expr $PERCENT \* 50 / 100` SYSCRITICAL=`expr $PERCENT \* 80 / 100` USRWARNING=`expr $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.colour ffffff" 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 if [ ! -z "$extextinfo" ]; then echo "steal.label steal" echo "steal.draw STACK" echo "steal.min 0" echo "steal.type DERIVE" echo "steal.info The time that a virtual CPU had runnable tasks, but the virtual CPU istself was not running" fi } fetch_cpu() { extinfo="" extextinfo="" 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" 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,\} \{1,\}[0-9]\{1,\}' /proc/stat >/dev/null 2>&1; then extextinfo="steal" fi 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 if [ ! -z "$extextinfo" ]; then echo "steal.value" $(echo "$CINFO" | cut -d\ -f8) fi } 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.\n" 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" `expr $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=`expr $MEMTOTAL - $MEMFREE - $BUFFERS - $CACHED` SWAP=`expr $SWAP_TOTAL - $SWAP_FREE` echo "buffers.value" `expr $BUFFERS \* 1024` echo "swap.value" `expr $SWAP \* 1024` echo "cached.value" `expr $CACHED \* 1024` echo "free.value" `expr $MEMFREE \* 1024` if [ "$SLAB" != "" ]; then echo "slab.value" `expr $SLAB \* 1024` APPS=`expr $APPS - $SLAB` fi if [ "$SWAPCACHED" != "" ]; then echo "swap_cache.value" `expr $SWAPCACHED \* 1024` APPS=`expr $APPS - $SWAPCACHED` fi if [ "$PAGETABLES" != "" ]; then echo "page_tables.value" `expr $PAGETABLES \* 1024` APPS=`expr $APPS - $PAGETABLES` fi if [ "$VMALLOCUSED" != "" ]; then echo "vmalloc_used.value" `expr $VMALLOCUSED \* 1024` APPS=`expr $APPS - $VMALLOCUSED` fi if [ "$COMMITTEDAS" != "" ]; then echo "committed.value" `expr $COMMITTEDAS \* 1024` fi if [ "$MAPPED" != "" ]; then echo "mapped.value" `expr $MAPPED \* 1024` fi if [ "$ACTIVE" != "" ]; then echo "active.value" `expr $ACTIVE \* 1024` fi if [ "$ACTIVEANON" != "" ]; then echo "active_anon.value" `expr $ACTIVEANON \* 1024` fi if [ "$ACTIVECACHE" != "" ]; then echo "active_cache.value" `expr $ACTIVECACHE \* 1024` fi if [ "$INACTIVE" != "" ]; then echo "inactive.value" `expr $INACTIVE \* 1024` fi if [ "$INACTDIRTY" != "" ]; then echo "inact_dirty.value" `expr $INACTDIRTY \* 1024` fi if [ "$INACTLAUNDRY" != "" ]; then echo "inact_laundry.value" `expr $INACTLAUNDRY \* 1024` fi if [ "$INACTCLEAN" != "" ]; then echo "inact_clean.value" `expr $INACTCLEAN \* 1024` fi echo "apps.value" `expr $APPS \* 1024` } config_load() { echo "graph_title Load average" echo "graph_args --base 1000 -l 0" echo "graph_vlabel load" echo "graph_scale no" echo "graph_category system" echo "load.label load" echo "load.warning 10" echo "load.critical 120" echo "graph_info The load average of the machine describes how many processes are in the run-queue (scheduled to run \"immediately\")." echo "load.info Average load for the five minutes." } fetch_load() { echo "load.value" $(cut -f2 -d\ /proc/loadavg) } 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_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" echo "graph_args --base 1000 -l 0" echo "graph_vlabel interrupts / \${graph_period}" echo "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`expr 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-`expr 1 + $CPUS`") VALUE=0 for VAL in $VALS; do VALUE=`expr $VALUE + $VAL` done echo "i$ID.value $VALUE" done } 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 $1 network interface. Please note that the traffic is shown in bits per second, not bytes." 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,*" } 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_uptime() { echo "graph_title Uptime" echo "graph_category system" 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) } # ===== NODE CODE ===== do_list() { echo $PLUGINS } do_nodes() { echo $HOSTNAME echo "." } do_config() { if ! echo "$PLUGINS" | grep "\b$1\b" >/dev/null 2>&1 || [ -z $1 ]; then echo "# Unknown service" else config_$1 fi echo "." } do_fetch() { if ! echo "$PLUGINS" | grep "\b$1\b" >/dev/null 2>&1 || [ -z $1 ]; then echo "# Unknown service" else fetch_$1 fi echo "." } do_version() { echo "munins node on $HOSTNAME version: $VERSION (munin-lite)" } do_quit() { exit 0 } # ===== RUNTIME CONFIG ===== RES="" for PLUGIN in $PLUGINS do if [ "$PLUGIN" = "if_" ] || [ "$PLUGIN" = "if_err_" ]; then plugin=${PLUGIN:0:$((${#PLUGIN}-1))} for INTERFACE in $(grep '^ *\(ppp\|eth\|wlan\|ath\|ra\|ipsec\)\([^:]\)\{1,\}:' /proc/net/dev | cut -f1 -d: | sed 's/ //g'); do INTERRES=$(echo $INTERFACE | sed 's/\./VLAN/') RES="$RES $PLUGIN$INTERRES" eval "fetch_${PLUGIN}${INTERRES}() { fetch_$plugin $INTERFACE $@; };" eval "config_${PLUGIN}${INTERRES}() { config_$plugin $INTERFACE $@; };" done elif [ "$PLUGIN" = "plugindir_" ]; then for MYPLUGIN in $(ls -1 $PLUGINPATTERN 2>/dev/null ); do if [ -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 $PLUGIN" fi done PLUGINS=$(echo $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 || [ -z $arg0 ] ; 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