NET-SNMP Linux disk IO collector, mark III
Fri, 12 May 2006 17:02Ok, this might be the last one ;-)
As mentioned previously, I've been writing a script that net-snmp can pass off the UCD-DISKIO-MIB requests to, for those versions that don't have it built in, and to save one from rebuilding net-snmp packages.
This time around, I've added support for 2.4 series kernels, which use /proc/partitions instead of /proc/diskstats to log the disk IO stats.
I've now got this running in production across a handful of machines, and it's pretty neat -- I am able to see the shape of disk traffic during a vacuum on one of our machines, alongside the CPU and memory usage, and load average graphs, for example.
As before, plop it into /usr/local/sbin/snmp-diskio-collector and add this line to your snmpd.conf:
pass .1.3.6.1.4.1.2021.13.15 /usr/local/sbin/snmp-diskio-collector
Here's the script:
#!/bin/sh
# by Jamie Wilkinson <jamie@anchor.net.au>
# this code is in the public domain
# based on passtest from the net-snmp distribution examples
# WARNING there is shitloads of IO required to get this information :)
debug_flag=0
debug () {
if [ $debug_flag -eq 1 ]; then
echo $* >> /tmp/snmp-diskio-collector-debug.log
fi
}
PLACE=".1.3.6.1.4.1.2021.13.15"
REQ="$2"
debug
debug "new run"
debug "args $*"
if [ "$1" = "-s" ]; then
exit 0
fi
# the 'tail' of the oid, everything after $PLACE
oidtail=`echo $REQ | sed "s/^$PLACE//"`
debug "oidtail=$oidtail"
# number of devices we can export
if [ -f /proc/diskstats ]; then
devcount=`wc -l /proc/diskstats | sed 's/^ *//' | cut -f1 -d' '`
else
devcount=`wc -l /proc/partitions | sed 's/^ *//' | cut -f1 -d' '`
devcount=`expr $devcount - 2`
fi
debug "devcount=$devcount"
item=`echo $oidtail | cut -f4 -d.`
index=`echo $oidtail | cut -f5 -d.`
debug "oidtail=$oidtail, item=$item, index=$index"
if [ "$1" = "-n" ]; then
if [ -z "$item" ]; then
item=1
index=1
elif [ -z "$index" ]; then
index=1
else
index=`expr $index + 1`
if [ "$index" -gt "$devcount" ]; then
index=1
item=`expr $item + 1`
if [ "$item" -gt 6 ]; then
# break out of the loop
exit 0;
fi
fi
fi
RET=$PLACE.1.1.$item.$index
else
case "$REQ" in
$PLACE) exit 0;;
*) RET=$REQ ;;
esac
fi
debug "after -n, item=$item, index=$index"
debug "RET is now $RET"
echo "$RET"
debug "oidtail=$oidtail, item=$item, index=$index"
# awk uses this variable in the environment below
export index
# see linux kernel Documentation/iostats.txt for format
if [ -n "$index" ]; then
case "$item" in
1)
# diskIOIndex
debug "result: diskIOIndex $index"
echo "integer"
echo $index
exit 0
;;
2)
# diskIODevice
debug "result: diskIODevice $index"
echo "string"
if [ -f /proc/diskstats ]; then
awk 'FNR == ENVIRON["index"] { print $3 }' /proc/diskstats
else
awk 'FNR == ENVIRON["index"] + 2 { print $4 }' /proc/partitions
fi
exit 0
;;
3)
# diskIONRead
debug "result: diskIONRead $index"
echo "counter"
if [ -f /proc/diskstats ]; then
awk 'FNR == ENVIRON["index"] { print $6 }' /proc/diskstats
else
awk 'FNR == ENVIRON["index"] + 2 { print $7 }' /proc/partitions
fi
exit 0
;;
4)
# diskIONWritten
debug "result: diskIONWritten $index"
echo "counter"
if [ -f /proc/diskstats ]; then
awk 'FNR == ENVIRON["index"] { print $10 }' /proc/diskstats
else
awk 'FNR == ENVIRON["index"] + 2 { print $11 }' /proc/partitions
fi
exit 0
;;
5)
# diskIOReads
debug "result: diskIOReads $index"
echo "counter"
if [ -f /proc/diskstats ]; then
awk 'FNR == ENVIRON["index"] { print $4 }' /proc/diskstats
else
awk 'FNR == ENVIRON["index"] + 2 { print $5 }' /proc/partitions
fi
exit 0
;;
6)
# diskIOWrites
debug "result: diskIOWrites $index"
echo "counter"
if [ -f /proc/diskstats ]; then
awk 'FNR == ENVIRON["index"] { print $8 }' /proc/diskstats
else
awk 'FNR == ENVIRON["index"] + 2 { print $9 }' /proc/partitions
fi
exit 0
;;
*) exit 0; #echo "string"; echo "debug... $RET $REQ"; exit 0 ;;
esac
else
exit 0
fi