#!/bin/bash # mrtg-data, based on a perl script by Nemo from 1999. # Copyright (c) 2003 Aaron Haviland # http://parsed.net/mrtg-data/ # # This program is free software; you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation; either version 2 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more # details. # # You should have received a copy of the GNU General Public License along with # this program; if not, write to the Free Software Foundation, Inc., 59 Temple # Place, Suite 330, Boston, MA 02111-1307 USA # Version 0.1 # First release # 0.1.1 # - fixed bug where the interface stats weren't being read properly. # unknown cause. # - subtract buffers from used memory. don't subtract cached. # 0.1.2 - 20031109 # - some more bashism speedups added # 0.1.3 - 20070729 # - added support for /proc/sys/kernel/random # We need these for everything. Get them out of the way. UPTIME=$(< /proc/uptime) UPTIME=${UPTIME% *} # /60? i don't know. HOSTNAME=$(< /proc/sys/kernel/hostname) VERSION=0.1.2 function showhelp () { cat <<-EOF $(basename $0) v$VERSION - addon utility for MRTG Syntax: $(basename $0) [family] [options] [device] Where family is one of: inet - network activity disk - space usage load - system load average mem - memory and swap usage activity - disk activity io - io_status (linode only) entropy - random number entropy pool usage Examples of devices are: Family Devices inet eth0 (default), ppp0, lo disk total (default), /, /usr/local/, /tmp (specify the mountpoint of the partition) load n/a mem n/a activity 98 (ubd is device major 98) io n/a entropy n/a Options: Family Options inet -p Show packets instead of bytes. EOF exit 0; } # we can use linux/netdevice.h # struct net_device_stats # unsigned long rx_bytes, rx_packets, tx_bytes, tx_packets #alternately, see the source for ifconfig (in net-tools) function inet () { if [[ "${1}" = "-p" ]]; then DOPACKETS=1 shift else DOPACKETS=0 fi # if no interface is specified, use eth0 if [[ "${1}z" = "z" ]]; then IFACE="eth0" else IFACE="${1}" fi TMP="$(grep "$IFACE:" /proc/net/dev)" declare -a NETDEV="(${TMP#*:})" BYTESIN=${NETDEV[0]} PACKETSIN=${NETDEV[1]} BYTESOUT=${NETDEV[8]} PACKETSOUT=${NETDEV[9]} if [[ $DOPACKETS -eq 1 ]]; then echo $PACKETSIN echo $PACKETSOUT else echo $BYTESIN echo $BYTESOUT fi } function mem () { KERNVER=$(uname -r) case $KERNVER in 2.2*|2.4*) declare -a MEM="($(grep "^Mem:" /proc/meminfo))" declare -a SWAP="($(grep "^Swap:" /proc/meminfo))" echo "$[ ${MEM[2]} - ${MEM[5]}]" echo "${SWAP[2]}" ;; 2.6*) declare -a MEMTOT="($(grep "^MemTotal:" /proc/meminfo))" declare -a MEMFREE="($(grep "^MemFree:" /proc/meminfo))" declare -a SWAPTOT="($(grep "^SwapTotal:" /proc/meminfo))" declare -a SWAPFREE="($(grep "^SwapFree:" /proc/meminfo))" echo "$[ ( ${MEMTOT[1]} - ${MEMFREE[1]} ) * 1024 ]" echo "$[ ( ${SWAPTOT[1]} - ${SWAPFREE[1]} ) * 1024 ]" ;; esac } function io (){ declare -a IO="($(< /proc/io_status))" TMP=${IO[2]#*=} echo $(($TMP / 1000)) echo ${IO[3]#*=} } function entropy () { declare -a ENTROPY="($(< /proc/sys/kernel/random/entropy_avail))" declare -a POOLSIZE="($(< /proc/sys/kernel/random/poolsize))" echo $ENTROPY echo $POOLSIZE } function load () { declare -a LOADAVG="($(< /proc/loadavg))" echo ${LOADAVG[0]/./} echo ${LOADAVG[3]/*\//} } # FIXME # i'm sorry. devfs messes us up. if the path to your partition is too # long, df wraps. function disk () { if [[ "${1}" = "total" || "${1}z" = "z" ]] ; then df -k -t ext3 -t ext2 -t vfat -t reiserfs | \ while read -a i; do if [[ "${i[0]}" != "Filesystem" ]]; then total=$[ $total + ${i[1]} ] used=$[ $used + ${i[2]} ] echo $used echo $total fi done | tail -n 2 else declare -a i="($(df -k $1 | tail -n1))" echo ${i[2]} echo ${i[3]} fi } # on 2.2, we use /proc/stat # disk_rio # on 2.4, we use /proc/stat # disk_io (major,minor):(read+write-requests,read-requests,read-sectors,write-requests,write-sectors) # on 2.6, we can use /proc/diskstats # major minor device reads 0 0 0 writes 0 0 0 0 0 0 # or /sys/block/device/[partition/]stat # device: # reads 0 0 0 writes 0 0 0 0 0 0 # partition: # reads 0 writes 0 # sysfs is slightly faster (.004-.005s vs .004-.010s) and wouldn't # require an external grep. we prefer that. function activity () { KERNVER=$(uname -r) case $KERNVER in 2.2.*) echo "Linux 2.2 support isn't written at this time" ;; 2.4.*) TMP=$(grep "($1," /proc/stat) TMP=${TMP##*(} declare -a ACTIVITY="(${TMP//,/ })" echo "${ACTIVITY[1]}" echo "${ACTIVITY[3]}" ;; 2.5.*|2.6.*) if [[ -d /sys/block ]]; then TMP1="/sys/block/$1/stat" TMP2="/sys/block/${1:0:$[${#1} - 1 ]}/$1/stat" if [[ -e $TMP1 ]]; then declare -a j="($(< $TMP1))" echo ${j[0]} echo ${j[4]} elif [[ -e $TMP2 ]]; then declare -a j="($(< $TMP2))" echo ${j[0]} echo ${j[2]} fi else declare -a TMP="($(grep $1 /proc/diskstats | head -n1))" if [[ "${1/[0-9]/}" = "$1" ]]; then # we're dealing with the drive echo ${TMP[3]} echo ${TMP[7]} else # we're dealing with a partition echo ${TMP[3]} echo ${TMP[5]} fi fi ;; esac } if [[ "${1}z" = "z" ]]; then showhelp else case $1 in inet) inet $2 $3 ;; disk) disk $2 ;; mem) mem ;; load) load ;; activity) activity $2 ;; io) io ;; entropy) entropy ;; uptime) echo $[ ${UPTIME%.*} / 60 ] echo 0 ;; *) showhelp ;; esac fi echo $UPTIME echo $HOSTNAME exit 0;