#!/bin/sh
# Memory Leak Detector v1.0 http://www.galstar.com/~jmccorm/leak
# by Josh McCormick (jmccorm@galstar.com)
# Tested on Solaris 2.5.1 and Solaris 2.6. Your mileage may vary.
# BASEDIR is the directory for the "leak" application. Put the script here.
# It'll create two subdirectories "leakdir1" and "leakdir2" and populate
# them with data. (leakdir1 contains the baseline, leakdir2 contains
# data currently being parsed)
BASEDIR="/tmp/leak"
# NOTE: This script only detects leaks in applications that were running
# when you created the baseline. The baseline is created when you first
# run the program, or "leakdir1" has been nuked. If new processes start
# after you have created the baseline and they start leaking, they will
# not register. If you reboot the system, you'll need to create a new
# baseline. Again, to create a new baseline, nuke the "leakdir1"
# subdirectory.
# CYA: Use at your own risk. I do not program for a living.
# ITCH: This script was created to find leaks in long-running programs.
if [ ! -d $BASEDIR ]
then
echo "$BASEDIR does not exist. Creating..."
mkdir $BASEDIR
fi
if [ ! -d $BASEDIR/leakdir1 ]
then
echo "$BASEDIR/leakdir1 does not exist. Creating..."
mkdir $BASEDIR/leakdir1
if [ ! -d $BASEDIR/leakdir1 ]
then
echo "Unable to create directory! ABORTING..."
exit 99
fi
fi
if [ ! -d $BASEDIR/leakdir2 ]
then
echo "$BASEDIR/leakdir2 does not exist. Creating..."
mkdir $BASEDIR/leakdir2
if [ ! -d $BASEDIR/leakdir2 ]
then
echo "Unable to create directory! ABORTING..."
exit 99
fi
fi
if [ ! -f $BASEDIR/leak.log ]
then
echo "$BASEDIR/leak.log does not exist. Creating..."
touch $BASEDIR/leak.log
if [ ! -f $BASEDIR/leak.log ]
then
echo "Unable to create log file! ABORTING..."
exit 99
fi
fi
echo "" >> $BASEDIR/leak.log
echo "Scanning currently running processes..." >> $BASEDIR/leak.log
# Extract the current process list into leakdir2
for i in `ps -eo pid | grep -v PID`
do
echo `ps -o vsz -p $i | grep -v VSZ` > $BASEDIR/leakdir2/$i.vsz
echo `ps -o args -p $i | grep -v ARGS` > $BASEDIR/leakdir2/$i.args
done
date > $BASEDIR/leakdir2/.date
echo "" >> $BASEDIR/leak.log
if [ ! -f $BASEDIR/leakdir1/.date ]
then
echo "No previous information exists to compare against." >> $BASEDIR/leak.log
echo "Saving this scan as the baseline for future comparison." >> $BASEDIR/leak.log
echo "" >> $BASEDIR/leak.log
rm -R $BASEDIR/leakdir1
mv $BASEDIR/leakdir2 $BASEDIR/leakdir1
mkdir $BASEDIR/leakdir2
exit 99
fi
echo "Current time/date: `date`" >> $BASEDIR/leak.log
echo "Comparing for size change against baseline created on `cat $BASEDIR/leakdir1/.date`..." >> $BASEDIR/leak.log
# Get the process numbers of all items in leakdir1
for i in `ls -1 $BASEDIR/leakdir1 | cut -d "." -f 1 | sort | uniq`
do
diff $BASEDIR/leakdir1/$i.args $BASEDIR/leakdir2/$i.args > /dev/null 2>&1
if [ $? = 0 ]
then
diff $BASEDIR/leakdir1/$i.vsz $BASEDIR/leakdir2/$i.vsz > /dev/null 2>&1
if [ $? = 1 ]
then
echo "" >> $BASEDIR/leak.log
#echo "Virtual size of PID $i has changed!"
OLDVSZ=`cat $BASEDIR/leakdir1/$i.vsz`
NEWVSZ=`cat $BASEDIR/leakdir2/$i.vsz`
echo ----- OLD VSZ: $OLDVSZ k NEW VSZ: $NEWVSZ k CHANGE: `echo $NEWVSZ - $OLDVSZ | bc` k ----- >> $BASEDIR/leak.log
ps -o user,pid,args -p $i >> $BASEDIR/leak.log
fi
fi
done
echo "" >> $BASEDIR/leak.log