Wednesday, June 4, 2008

Shell Script To Monitor Disk Usage On Linux and Unix

Hey There,

Today, we're going to take a look at a simple shell script to monitor disk space usage. It's been quite a while since we've touch on that, going back to a post from last November regarding finding space hogs on overlay mounts. The script has been kept simple (basically checking every partition for one fixed percentage full) to highlight other features.

The main intent here was to set up a monitor that would be able to handle a variety of Linux and Unix Operating Systems (all dependant on the "uname -s" output from that system) and focus on that area distinctly. We've limited our initial list to HP-UX, Solaris, SCO and OpenBSD.

In this case we're using a simple case statement to enumerate through the four *nix's we have listed here. Obviously, we could easily add more operating systems, and their variations of the "df" command, to our list and, if it ever got too big, either roll them into an array or simplify the script so that more OS's would fall under the same umbrella.

Also, notice that we're stepping through parsing of the df output more tediously than is actually necessary. For instance, the creation of the df output could be parsed with sed all in one fell swoop. Again, although it is generally considered best practice to compact your script/code, our hope here was that this would be easy to follow for as many people as possible. Some folks learn better by tackling the tough-stuff and working back to basics and some of us learn better by starting with the basics and putting them all together to create the tough-stuff. It's a long and convoluted statement of philosophy, to be sure, but fairly descriptive of what we actually mean ;)

If you prefer, on the line where we parse the TABLE file and trim it with sed, you can take out this part (or add to it) as it was placed in there as an example of how to ignore a specific partition (/usr):

-e '/usr$/d'

So, the line:

sed -e '1d' -e '/usr$/d' ${BASEDIR}/TABLE >> ${BASEDIR}/TABLE2

could be changed to:

sed -e '1d' ${BASEDIR}/TABLE >> ${BASEDIR}/TABLE2

which could then be simplified even further (since you don't need to use -e, even though it's okay to, if you only have one instruction to pass to sed) to become this:

sed '1d' ${BASEDIR}/TABLE >> ${BASEDIR}/TABLE2

And the entire script could be thusly compacted and streamlined, etc.
In any event, I hope this can be of some help (or, at least, an inspiration to reach higher ;) to you!

Best wishes,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/ksh

#
# dfvk.sh - Check partition % full
# across multiple OS'
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

trap 'rm -f ${BASEDIR}/TABLE ${BASEDIR}/TABLE2 ${BASEDIR}/MAILER;exit 1' 1 2 3 15

#BASEDIR="/tmp"
BASEDIR="tmp"
LOGHOST=`hostname`
MAILEES="you@yourhost.com"
LIMIT=90
OSVERSION=`uname -s`

case $OSVERSION in

SunOS | OpenBSD )
df -k >> ${BASEDIR}/TABLE
;;
HP-UX )
bdf >> ${BASEDIR}/TABLE
;;
* )
df -v >> ${BASEDIR}/TABLE
;;

esac

echo "$LOGHOST is getting ready to bother you!" >> ${BASEDIR}/MAILER
echo >> ${BASEDIR}/MAILER

sed -e '1d' -e '/usr$/d' ${BASEDIR}/TABLE >> ${BASEDIR}/TABLE2
sed 's/%//g' ${BASEDIR}/TABLE2 > ${BASEDIR}/TABLE
cat ${BASEDIR}/TABLE |while read ONE TWO THREE FOUR FIVE SIX
do

case $OSVERSION in

HP-UX | SunOS | OpenBSD )
if [ $FIVE -gt $LIMIT ]
then
print "$SIX partition at ${FIVE}% capacity" >> ${BASEDIR}/MAILER
else
continue
fi
break;;
* )
if [ $SIX -gt $LIMIT ]
then
print "$ONE partition at ${SIX}% capacity" >> ${BASEDIR}/MAILER
else
continue
fi
break;;

esac

done

MAILCOUNT=`cat ${BASEDIR}/MAILER |wc -l`
if [ $MAILCOUNT -gt 2 ]
then
cat ${BASEDIR}/MAILER |mailx -s "$LOGHOST : Potential Paging Threat!" $MAILEES
fi

rm -f ${BASEDIR}/TABLE ${BASEDIR}/TABLE2 ${BASEDIR}/MAILER


, Mike