#!/bin/sh
# $Id: bb-memory.sh,v 3.1 2004/02/12 22:49:41 henrik Exp $
#
# @(#)bb-memory.sh	Bennett Samowich <brs@ben-tech.com>
# External script to check physical and swap memory usage.
#
# 12/21/1999 - Original posting included support for Linux and Solaris.
#                               Todd Jimenez <tjimenez@outpost.com>
# 01/03/2000 - Modified to this format and added AIX and HPUX support.
#                               Bennett Samowich <brs@ben-tech.com>
# 07/19/2000 - OSF1/Digital UNIX/Tru64 support added
#				Dean Thayer <deanthayer@netscape.net>
# 07/21/2000 - Modified Linux to test actual memory usage
#	       Fixed the prtconf path error in solaris
#				Tal Ovadia <tal@jalan.com>
# 07/27/2000 - Added Debian support as confirmed by Christian Perrier
#              <Christian.Perrier@onera.fr>
#				Bennett Samowich <brs@ben-tech.com>
# 08/23/2000 - Added Irix support as confirmed by Paco Culebras Amigo
#              <paco@bellsola.com>
#				Bennett Samowich <brs@ben-tech.com>
# 08/24/2000 - Added handling for tests that may not be performed.
#              Recommended by Mike Rowell <miker@xciv.org>.
#              Also, fixed divide by zero bug in percentage calculations.
#				Bennett Samowich <brs@ben-tech.com>
# 05/24/2001 - Added a small c program for HP-UX to figure out how much
#              memory is in the machine.  dmesg failed when there were
#              many kernel messages.
#                               Ian Prowell <iprowell@yahoo.com>
# 12/30/2001 - Fixed some minor formatting issues when data is sent to the
#              $BBDISPLAY. David Fetter <megasurg@setec-astronomy.org>
# 02/12/2004 - Maintenance shifts to Henrik Storner <henrik-bb@hswn.dk>
#              Merged changes from www.deadcat.net for HP-UX and BSD/OS
#
#######################################################################

# VERSION INFORMATION
VERSION="\$Id: bb-memory.sh,v 3.1 2004/02/12 22:49:41 henrik Exp $"

#
# SCRIPTS IN THE BBHOME/ext DIRECTORY ARE ONLY RUN IF
# LISTED IN THE BBEXT VARIABLE OF $BBHOME/runbb.sh
# THIS IS FOR SECURITY.
#

#
# BBPROG SHOULD JUST CONTAIN THE NAME OF THIS FILE
# USEFUL WHEN YOU GET ENVIRONMENT DUMPS TO LOCATE
# THE OFFENDING SCRIPT...
#
BBPROG=bb-memory.sh; export BBPROG

#
# TEST NAME: THIS WILL BECOME A COLUMN ON THE DISPLAY
# IT SHOULD BE AS SHORT AS POSSIBLE TO SAVE SPACE...
# NOTE YOU CAN ALSO CREATE A HELP FILE FOR YOUR TEST
# WHICH SHOULD BE PUT IN www/help/$TEST.html.  IT WILL
# BE LINKED INTO THE DISPLAY AUTOMATICALLY.
#
TEST="memory"

#
# BBHOME CAN BE SET MANUALLY WHEN TESTING.
# OTHERWISE IT SHOULD BE SET FROM THE BB ENVIRONMENT
#
# BBHOME=/home/sean/bb; export BBHOME   # FOR TESTING

if test "$BBHOME" = ""
then
        echo "BBHOME is not set... exiting"
        exit 1
fi

if test ! "$BBTMP"                      # GET DEFINITIONS IF NEEDED
then
         # echo "*** LOADING BBDEF ***"
        . $BBHOME/etc/bbdef.sh          # INCLUDE STANDARD DEFINITIONS
fi

#
# NOW COLLECT SOME DATA
# IN THIS CASE, IT'S THE CURRENT MEMORY USAGE OF THE SYSTEM

# SELECT SOME LEVELS... GREEN IS THE DEFAULT...
#
# Use Physical levels for Solaris and Actual levels for FreeBSD and Linux

PERCENT_PHYS_WARN="100"         # GO YELLOW AT THIS LEVEL
PERCENT_PHYS_PANIC="100"        # GO RED AND PAGE AT THIS LEVEL
PERCENT_ACT_WARN="90"           # GO YELLOW AT THIS LEVEL
PERCENT_ACT_PANIC="99"          # GO RED AND PAGE AT THIS LEVEL
PERCENT_SWAP_WARN="60"          # GO YELLOW AT THIS LEVEL
PERCENT_SWAP_PANIC="99"         # GO RED AND PAGE AT THIS LEVEL


# INITIALIZE SOME VALUES
PHYS_MEMORY=0
PHYS_MEMORY_USED=-1
ACT_MEMORY=0
ACT_MEMORY_USED=-1
SWAP_MEMORY=0
SWAP_MEMORY_USED=-1

# The following operating systems are supported:
case $BBOSTYPE in
   linux | redhat | debian | fedora )
      FREE=`/usr/bin/free -m`

      FREE_PHYS=`echo "$FREE" | $GREP "Mem"`
      FREE_ACT=`echo "$FREE" | $GREP "+"`
      FREE_SWAP=`echo "$FREE" | $GREP "Swap"`

      PHYS_MEMORY=`echo $FREE_PHYS | $AWK '{ print $2; }'`
      PHYS_MEMORY_USED=`echo $FREE_PHYS | $AWK '{ print $3; }'`
      ACT_MEMORY_USED=`echo $FREE_ACT | $AWK '{ print $3; }'`
      SWAP_MEMORY=`echo $FREE_SWAP | $AWK '{ print $2; }'`
      SWAP_MEMORY_USED=`echo $FREE_SWAP | $AWK '{ print $3; }'`
      ;;
   solaris )
      PRTCONF=`/usr/sbin/prtconf`

      PHYS_MEMORY=`echo "$PRTCONF" | $GREP "Mem" | $AWK '{print $3}'`
		
      VMSTAT=`/bin/vmstat 1 2 | $TAIL -1`

      PHYS_MEMORY_FREE=`echo $VMSTAT | $AWK '{print $5;}'`
      PHYS_MEMORY_FREE=`$EXPR $PHYS_MEMORY_FREE / 1024`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`

      SWAP=`/usr/sbin/swap -s`
      SWAP_MEMORY_USED=`echo $SWAP | $AWK '{print $9}' | $SED 's/k//'`
      SWAP_MEMORY_USED="`$EXPR $SWAP_MEMORY_USED / 1024`"

      SWAP_MEMORY_FREE=`echo $SWAP | $AWK '{print $11}' | $SED 's/k//'`
      SWAP_MEMORY_FREE="`$EXPR $SWAP_MEMORY_FREE / 1024`"
      SWAP_MEMORY="`$EXPR $SWAP_MEMORY_USED + $SWAP_MEMORY_FREE`"
      ;;
   aix )
      MEMORY=`bootinfo -r`
      
      PHYS_MEMORY=`$EXPR $MEMORY / 1024`

      VMSTAT=`/usr/bin/vmstat 1 2 | $TAIL -1`

      PHYS_MEMORY_FREE=`echo $VMSTAT | $AWK '{print $4;}'`
      PHYS_MEMORY_FREE=`$EXPR $PHYS_MEMORY_FREE / 256`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`

      SWAP=`pstat -s`
      SWAP_MEMORY_USED=`echo $SWAP | $AWK '{print $7}'`
      SWAP_MEMORY_USED=`$EXPR $SWAP_MEMORY_USED / 256`
      SWAP_MEMORY_FREE=`echo $SWAP | $AWK '{print $8}'`
      SWAP_MEMORY_FREE=`$EXPR $SWAP_MEMORY_FREE / 256`
      SWAP_MEMORY=`$EXPR $SWAP_MEMORY_FREE + $SWAP_MEMORY_USED`
      ;;
   hpux )
      PHYS_MEMORY=`$BBHOME/bin/bb-hp-memsz -p`
      PHYS_MEMORY_FREE=`$BBHOME/bin/bb-hp-memsz -f`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`

      SWAPINFO=`/usr/sbin/swapinfo -tm | $GREP "total"`
      SWAP_MEMORY=`echo $SWAPINFO | $AWK '{print $2}'`
      SWAP_MEMORY_USED=`echo $SWAPINFO | $AWK '{print $3}'`
      SWAP_MEMORY_FREE=`echo $SWAPINFO | $AWK '{print $3}'`
      ;;
   osf )	
      VMSTAT='/bin/vmstat -P'
      PHYS_MEMORY=`$VMSTAT | $GREP "Total Physical Memory" | \
         $AWK {'print $5'} | $HEAD -n 1 | cut -d. -f1`
      PHYS_MEMORY_KB=`$EXPR $PHYS_MEMORY \* 1024`
      PHYS_MEMORY_FREE_PAGES=`$VMSTAT | $GREP "free pages" | $AWK {'print $4'}`
      PHYS_MEMORY_FREE_KB=`$EXPR $PHYS_MEMORY_FREE_PAGES \* 8`
      PHYS_MEMORY_USED_KB=`$EXPR $PHYS_MEMORY_KB - $PHYS_MEMORY_FREE_KB`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY_USED_KB / 1024`

      SWAPON='/sbin/swapon -s'
      SWAP_MEMORY_PAGES=`$SWAPON | $GREP "Allocated space:" | \
         $AWK {'print $3'} | $TAIL -n 1`
      SWAP_MEMORY=`$EXPR $SWAP_MEMORY_PAGES \* 8 / 1024`
      SWAP_MEMORY_USED_PAGES=`$SWAPON | $GREP "In-use space:" | \
         $AWK {'print $3'} | $TAIL -n 1`
      SWAP_MEMORY_USED=`$EXPR $SWAP_MEMORY_USED_PAGES \* 8 / 1024`
      ;;
   irix )
      TOP=`/usr/sbin/top -b | $GREP "Memory:"`
      PHYS_MEMORY=`echo $TOP | $AWK {'print $4'} | $SED 's/M//'` 
      PHYS_MEMORY_USED=`echo $TOP | $AWK {'print $4'} | $SED 's/M//'`
      PHYS_MEMORY_FREE=`echo $TOP | $AWK {'print $6'} | $SED 's/M//'`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`

      SWAP_MEMORY=`echo $TOP | $AWK {'print $8'} | $SED 's/M//'`
      SWAP_MEMORY_FREE=`echo $TOP | $AWK {'print $10'} | $SED 's/M//'`
      SWAP_MEMORY_USED=`$EXPR $SWAP_MEMORY - $SWAP_MEMORY_FREE` 
      ;;	
   bsdi4 )
      PHYS_MEMORY=`$AWK '/real mem/ { print $4 / 1048576;}' < /var/db/dmesg.boot`
      TOP=`/usr/contrib/bin/top -b | $GREP "Memory:"`
      PHYS_MEMORY_FREE=`echo $TOP | $AWK {'print $7'} | $SED 's/M//'`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`

      SWAP=`/usr/sbin/pstat -s | $TAIL -1`
      SWAP_MEMORY_USED=`echo $SWAP | $AWK '{print int($1 / 1024 + 0.5)}'`
      SWAP_MEMORY=`echo $SWAP | $AWK '{print int($6 / 1024 + 0.5)}'`
      SWAP_MEMORY_FREE=`$EXPR $SWAP_MEMORY - $SWAP_MEMORY_USED`
      ;;	
   freebsd )
      PHYS_MEMORY=`/sbin/sysctl -a | $GREP "hw.physmem:" | $AWK '{print int(($2 / 1024) / 1024 + 0.5)}'`
      TOP=`/usr/bin/top -b | $GREP "Mem:"`
      PHYS_MEMORY_FREE=`echo $TOP | $AWK {'print $12'} | $SED 's/M//'`
      PHYS_MEMORY_USED=`$EXPR $PHYS_MEMORY - $PHYS_MEMORY_FREE`
      FREE_ACT_INACT=`echo $TOP | $AWK {'print $4'} | $SED 's/M//'`
      FREE_ACT_CACHE=`echo $TOP | $AWK {'print $8'} | $SED 's/M//'`
      FREE_ACT=`$EXPR $FREE_ACT_INACT + $FREE_ACT_CACHE`
      ACT_MEMORY_USED=`$EXPR $PHYS_MEMORY - $FREE_ACT`

      SWAP=`/usr/sbin/pstat -s | $TAIL -1`
      SWAP_MEMORY_USED=`echo $SWAP | $AWK '{print int($3 / 1024 + 0.5)}'`
      SWAP_MEMORY=`echo $SWAP | $AWK '{print int($2 / 1024 + 0.5)}'`
      SWAP_MEMORY_FREE=`$EXPR $SWAP_MEMORY - $SWAP_MEMORY_USED`
      ;;        


   * )
      COLOR="clear"
      STATUS="??? Unknown ???"
      LINE="
Memory routine not defined for this operating system ($BBOSTYPE)"
      $BB $BBDISP "status $MACHINE.$TEST $COLOR `date` - $STATUS $LINE"
      exit 1
      ;;
esac

if [ $PHYS_MEMORY -eq 0 ]
then
        exit 0
fi

# CALCULATE THE PERCENTAGE OF MEMORY USED.  WE MUST
# ALSO COVER FOR THE DIVIDE-BY-ZERO POSSIBILITY.
PERCENT_PHYS_MEMORY_USED=0
PERCENT_ACT_MEMORY_USED=0
PERCENT_SWAP_MEMORY_USED=0
if [ $PHYS_MEMORY -gt 0 ]
then
   PERCENT_PHYS_MEMORY_USED=`$EXPR 100 \* $PHYS_MEMORY_USED / $PHYS_MEMORY`
   PERCENT_ACT_MEMORY_USED=`$EXPR 100 \* $ACT_MEMORY_USED / $PHYS_MEMORY`
fi
if [ $SWAP_MEMORY -gt 0 ]
then
   PERCENT_SWAP_MEMORY_USED=`$EXPR 100 \* $SWAP_MEMORY_USED / $SWAP_MEMORY`
fi


COLOR="green"
STATUS="Memory OK"

# CONSTRUCT THE STATUS LINE FOR THE PHYSYSICAL MEMORY USAGE.  IF THE TEST
# WAS NOT PERFORMED, THEN WE WILL DISPLAY WHAT INFORMATIOn WE HAVE
# ALONG WITH THE "CLEAR" MARKER TO SHOW THAT THE TEST WAS NOT PERFORMED.
if [ $PHYS_MEMORY_USED -ge 0 ]
then
   if [ $PERCENT_PHYS_MEMORY_USED -ge $PERCENT_PHYS_PANIC ]
   then
      COLOR="red"
      PHYS_COLOR="red"
      STATUS="Memory **very** low"
   else
      if [ $PERCENT_PHYS_MEMORY_USED -ge $PERCENT_PHYS_WARN ]
      then
         PHYS_COLOR="yellow"
         if [ "$COLOR" != "red" ]
         then
            COLOR="yellow"
            STATUS="Memory low"
         fi
      else
         PHYS_COLOR="green"
      fi
   fi
else
   PHYS_COLOR="clear"
fi

LINE="
   Memory	Used    Total	Percentage
&${PHYS_COLOR} Physical	${PHYS_MEMORY_USED}M	${PHYS_MEMORY}M	${PERCENT_PHYS_MEMORY_USED}%"

# CONSTRUCT THE STATUS LINE FOR THE ACTUAL MEMORY USAGE.  IF THE TEST
# WAS NOT PERFORMED, THEN WE WILL DISPLAY WHAT INFORMATIOn WE HAVE
# ALONG WITH THE "CLEAR" MARKER TO SHOW THAT THE TEST WAS NOT PERFORMED.
if [ $ACT_MEMORY_USED -ge 0 ]
then
   if [ $PERCENT_ACT_MEMORY_USED -ge $PERCENT_ACT_PANIC ]
   then
      COLOR="red"
      ACT_COLOR="red"
      STATUS="Memory **very** low"
   else
      if [ $PERCENT_ACT_MEMORY_USED -ge $PERCENT_ACT_WARN ]
      then
         ACT_COLOR="yellow"
         if [ "$COLOR" != "red" ]
         then
            COLOR="yellow"
            STATUS="Memory low"
         fi
      else
         ACT_COLOR="green"
      fi
   fi
else
   ACT_COLOR="clear"
fi

LINE="$LINE
&${ACT_COLOR} Actual		${ACT_MEMORY_USED}M	${PHYS_MEMORY}M	${PERCENT_ACT_MEMORY_USED}%"

# CONSTRUCT THE STATUS LINE FOR THE SWAP MEMORY USAGE.  IF THE TEST
# WAS NOT PERFORMED, THEN WE WILL DISPLAY WHAT INFORMATIOn WE HAVE
# ALONG WITH THE "CLEAR" MARKER TO SHOW THAT THE TEST WAS NOT PERFORMED.
if [ $SWAP_MEMORY_USED -ge 0 ]
then
   if [ $PERCENT_SWAP_MEMORY_USED -ge $PERCENT_SWAP_PANIC ]
   then
      COLOR="red"
      SWAP_COLOR="red"
      STATUS="Memory **very** low"
   else
      if [ $PERCENT_SWAP_MEMORY_USED -ge $PERCENT_SWAP_WARN ]
      then
         SWAP_COLOR="yellow"
         if [ "$COLOR" != "red" ]
         then
            COLOR="yellow"
            STATUS="Memory low"
         fi
      else
         SWAP_COLOR="green"
      fi
   fi
else
   SWAP_COLOR="clear"
fi

LINE="$LINE
&${SWAP_COLOR} Swap		${SWAP_MEMORY_USED}M	${SWAP_MEMORY}M	${PERCENT_SWAP_MEMORY_USED}%"

# ADD THE VERSION INFORMATION TO THE BOTTOM OF THE DISPLAY
# LINE="$LINE
#
# <FONT SIZE="-1">$VERSION</FONT>
# "

#
# AT THIS POINT WE HAVE OUR RESULTS.  NOW WE HAVE TO SEND IT TO
# THE BBDISPLAY TO BE DISPLAYED...
#
$BB $BBDISP "status $MACHINE.$TEST $COLOR `date` - $STATUS $LINE"

