#!/bin/sh
# File  : chk_procs
# By    : M. de Boer
# At    : 011030
# Mod   : Verion 2.1, 011031, M.de Boer, chk of CPU% added
# Mod   : Verion 2.2, 011031, M.de Boer, another ETC-file layout. Chk for
VERSION. # added in ETC-file
# Mod: V 2.3, 020124, M. de Boer, chk max. of procs. chk for defunct &
/etc-file with HOSTNAME
# Mod: v2.4, 020125, M. de Boer, more info with <defunct>
# Mod: v2.5, 020129, M. de Boer, more then 2 defuncts
# Mod: v2.6, 020225, M. de Boer, Added: -nodefuncts, -x, -nomail, $SAVE,
-nosave, MAXLOGSIZE
# Mod:v2.7,020305,M.de Boer, VERBOSE added & GNU like options & USAGE
# Mod:v2.8,020319,M.de Boer. DEFUNCTINFO in stead of NODEFUNCTS
# Mod:2.9,020321,M.de Boer, -nodefunctchk added.
# Mod:2.10,020909,M de boer, 2nd param (MAX) in etc-file ="" / 0 .
DEFUNCTCHK= default NO defunctchk & DEFUNCTINFO=
# Mod:2.11,021106,M.de Boer: At chk %: `sort -n | tail -1` added & $PGM
added with mail
# Mod:2.12,030628,MdB: If MAX < 1 -> If MAX < 0
# Mod:2.13,031017,MdB: echo "ERROR" > &2 
#  Check for major (x) version-numbers (in x.yy) for ETC-files
#  $PROC met spatie, zodat alleen de proc-naam wordt gezien & niet een deel
daarvan
#
# Subject: Checks existance (and max.), CPU% of the processes and <defunct>s
>From etc-file
#set -x

PGM="`basename $0`"
VERSION="2.13"
HOSTNAME="`hostname`"
LOG="/var/log/$PGM.log"
ETC="/usr/local/etc/$PGM.$HOSTNAME"
TMP="/tmp/$PGM"
SAVE="/tmp/$PGM.save"
USER="root"
MAIL=1
DEFUNCTINFO= 
MAXLOGSIZE=100   # In K's
DEFUNCTCHK= 
SCRIPTVER="`echo $VERSION |cut -d= -f2|cut -d. -f1`"

USAGE()
{
  echo "Usage: $PGM [-h] [-v] [-x] [--help] [--defunctchk] [--defunctinfo]
[--nomail] [--nosave]"
  echo "  Version: $VERSION"
  echo "  options:"
  echo "    -h : this help"
  echo "    -v : verbose"
  echo "    -x : set -x"
  echo "    --help          : this help"
  echo "    --defunctchk    : check for <defunct>'s"
  echo "    --defunctinfo   : give more info about <defunct>"
  echo "    --nomail        : do NOT send mail"
  echo "    --nosave        : do NOT save the missing proc's"
}

# Check & move LOG-file if longer then max.
touch $LOG
LOGSIZE=`du -ka $LOG | cut -f1`
if [ $LOGSIZE -ge $MAXLOGSIZE ]; then
  mv $LOG $LOG.old
  touch $LOG
  chmod 662 $LOG
fi 

rm -f $TMP 1> /dev/null 2>&1
echo "`date +%Y%m%d_%H%M%S` $0 (v$VERSION) started." | tee -a $LOG

# Check options
while [ $# -gt 0 ]
do
  case $1 in
    --defunctinfo) DEFUNCTINFO=1 ;;
    --defunctchk) DEFUNCTCHK=1 ;;
    --nomail) MAIL=0 ;;
    --nosave) NOSAVE=1 ;;
    -h | --help)
      USAGE
      exit 1
      ;;
    -v)
      VERBOSE=1
      ;;
    -x)  set -x ;;
    *)  echo "Option $1 not known."
        USAGE
        exit 1
    ;;
  esac
  shift
done


# If local ETC-file, then use this file
if [ -f "chk_procs.etc" ]; then
  ETC="chk_procs.etc"
fi
if [ ! -f $ETC ]; then
  echo "$PGM: NO etc-file ($ETC) available. Exiting ..." | tee -a $LOG >&2
  exit 2
fi

ETCVER="`grep VERSION $ETC |cut -d= -f2|cut -d. -f1`"
if [ $ETCVER != $SCRIPTVER ]; then
  echo "Version of etc-file ($ETC) is not equal to $VERSION. Exiting ..."
>&2
  exit 2
fi

# if -nosave (do not save missing proc's in a file), make the save file
empty, otherwise the `grep .. $SAVE` will give an error.
if [ $NOSAVE ]; then
  cp /dev/null $SAVE
fi
touch $SAVE

cat $ETC | grep -v '#' | while read LINE
do
  PROC="`echo $LINE | awk -F: '{print $1}'`"  # Proc-name
  CPU="`echo $LINE | awk -F: '{print $2}'`"  # Max CPU usage
  MAX="`echo $LINE | awk -F: '{print $3}'`"  # Max. (number of) existance of
proc. If "" do not check for existance. If 0 proc may NOT run
  if [ $VERBOSE ]; then
    echo "Process: $PROC >$CPU% >#=$MAX "
  fi

  PCPU="`ps -eo pcpu,args|grep -v grep|grep \"$PROC\"|cut -d'.' -f1|sort
-n|tail -1`"
  if [ "$PCPU" -gt "$CPU" ]; then
    echo "At $HOSTNAME CPU usage of process $PROC is too high ($PCPU%)
(max=$CPU%) " | tee -a $TMP | tee -a $LOG
  fi

  if [ "$MAX" != "" ]; then  # is MAX=empty then do not check for existance
    if [ "$MAX" = "0" ]; then  # If MAX=0 (a proc. may NOT exist), then
check if proc. exists.
      PCNT="`ps -ef | grep -v grep | grep \" $PROC \" | wc -l`"
      if [ "$PCNT" -gt "0" ]; then
        echo "At $HOSTNAME a number($PCNT) of $PROC exists. This may NOT
be." | tee -a $TMP | tee -a $LOG
      fi
    else
      if [ "$MAX" -gt "0" ]; then  # If MAX < 0, then check num. existance
        PCNT="`ps -ef | grep -v grep | grep \" $PROC \" | wc -l`"
        if [ "$PCNT" -gt "$MAX" ]; then
          echo "At $HOSTNAME number of $PROC is to high ($PCNT) (max=$MAX)"
| tee -a $TMP | tee -a $LOG
        fi
      fi
      PS="`ps -ef | grep -v grep | grep \" $PROC\" `" 1> /dev/null 2>&1
      if [ "$PS" = "" ]; then
        # Check if process was not running prev. time. (grep-exit=1 if not
found)
        grep "$PROC" $SAVE
        EXIT="$?"
        if [ "$EXIT" = "1" ]; then
          echo "At $HOSTNAME process $PROC is NOT running"  | tee -a $TMP |
tee -a $LOG | tee -a $SAVE
        else
          echo "\"$PROC\" found in $SAVE"
        fi
      else
        # proc. is found. Check if it was not running prev. time
(grep-exit=0 if found). The save will be emptied. So also the other proc's
will be cleaned!! This was easyer then deleteing one row in the SAVE-file
        grep "$PROC" $SAVE
        EXIT="$?"
        if [ "$EXIT" = "0" ]; then
          echo "At $HOSTNAME process $PROC is running again"  | tee -a $TMP
| tee -a $LOG 
          cp /dev/null $SAVE
        fi
      fi
    fi
  fi

done

# Chk for <defunct>'s if $DEFUNCTCHK"
if [ $DEFUNCTCHK ]; then
  DEFUNC_CNT="`ps -ef | grep -v grep | grep \<defunct\> | wc -l`"
  if [ $DEFUNC_CNT -gt 2 ]; then
    echo "At $HOSTNAME $DEFUNC_CNT <defunct>(s) found." | tee -a $TMP | tee
-a $LOG
    echo "`ps -ef | grep -v grep | grep \<defunct\>`" | tee -a $TMP | tee -a
$LOG
# DEFUNCTINFO means not displaying the defuncts. It will DO count the number
of defuncts.
    if [ $DEFUNCTINFO ]; then
      echo "More info (with parent proc.): " | tee -a $TMP
      for PPID in `ps -ef | grep -v grep | grep \<defunct\> | awk '{print
$3}'`
      do
        ps -ef | grep -v grep | grep $PPID | tee -a $TMP 
      done
    fi
  fi
fi


if [ -s $TMP ] ; then  # If size > 0
  if [ $MAIL ]; then
    echo "Options: DEFUNCTCHK=$DEFUNCTCHK DEFUNCTINFO=$DEFUNCTINFO
MAIL=$MAIL NOSAVE=$NOSAFE" | tee -a $TMP
    /usr/ucb/mail -s "$HOSTNAME:$PGM ($VERSION)" $USER < $TMP
  fi
#  rm -f $TMP
fi

echo "`date +%Y%m%d_%H%M%S` $0 finished." | tee -a $LOG
exit