#!/bin/sh
# written by Steve Murphy, with inspiration from Dmitry Vayntrub's check_uptime.sh
#
# The plugin shows the number of open files by postgres
# and allows you to set warn/crit values in case postgres
# 'leaks' open file descriptors.
#
#######################################################################
VERSION="check_postgres_ps v1.00"

# Exit-Codes:
STATE_OK=0
STATE_WARNING=1
STATE_CRITICAL=2
STATE_UNKNOWN=3

usage()
{
cat << EOF
usage: $0 [-C OPTION] [-c OPTION] [-M OPTION] [-m OPTION] [ -V ]

This script checks PostGreSQL process status parameters and optionally verifies if %mem/%cpu/thread
numbers are above treshholds

OPTIONS:
   -h   Help
   -C   CRITICAL MAX %CPU
   -c   WARNING  MAX %CPU
   -M   CRITICAL MAX %MEM
   -m   WARNING  MAX %MEM
   -V   Version
EOF
}

while getopts c:m:C:M:Vv OPTION
do
     case $OPTION in
	C)
	   CRITICAL_CPU=`echo $OPTARG | grep -v "^-"`
	   [ ! "$?" = 0 ] && echo "Error: missing or illegal option value" && \
	   exit $STATE_UNKNOWN
	   ;;
	c)
	   WARNING_CPU=`echo $OPTARG | grep -v "^-"`
	   [ ! "$?" = 0 ] && echo "Error: missing or illegal option value" && \
	   exit $STATE_UNKNOWN
	   ;;
	M)
	   CRITICAL_MEM=`echo $OPTARG | grep -v "^-"`
	   [ ! "$?" = 0 ] && echo "Error: missing or illegal option value" && \
	   exit $STATE_UNKNOWN
	   ;;
	m)
	   WARNING_MEM=`echo $OPTARG | grep -v "^-"`
	   [ ! "$?" = 0 ] && echo "Error: missing or illegal option value" && \
	   exit $STATE_UNKNOWN
	  ;;
	V)
	   echo $VERSION
	   exit $STATE_OK
	   ;;
	v)
	   VERBOSE=1
	   ;;
	?)
	   usage
	   exit $STATE_UNKNOWN
	   ;;
     esac
done
## get the pids of the master, logger, write, stats buffer, stats collector, and the 3 busiest daemons

PG_PROC=`cat /var/run/postmaster.5432.pid`
PGLOG=`ps -Aww -o pid,cmd | grep "postgres: logger process" | grep -v grep | awk '{ print $1}'`
PGWRT=`ps -Aww -o pid,cmd | grep "postgres: writer process" | grep -v grep | awk '{ print $1}'`
PGSTB=`ps -Aww -o pid,cmd | grep "postgres: stats buffer process" | grep -v grep | awk '{ print $1}'`
PGSTC=`ps -Aww -o pid,cmd | grep "postgres: stats collector process" | grep -v grep | awk '{ print $1}'`
PGD1=`ps -Aww -o pid,pcpu,time,cmd | grep "postgres: astium astium" | grep -v grep | sort -k 3 -k 2 -r | head -1 | awk '{ print $1}'`
PGD2=`ps -Aww -o pid,pcpu,time,cmd | grep "postgres: astium astium" | grep -v grep | sort -k 3 -k 2 -r | head -2 | tail -1 | awk '{ print $1}'`
PGD3=`ps -Aww -o pid,pcpu,time,cmd | grep "postgres: astium astium" | grep -v grep | sort -k 3 -k 2 -r | head -3 | tail -1 | awk '{ print $1}'`

# collect PCPU, PMEM from each proc

TEMPFILE=`mktemp -u /tmp/postgresinfo.XXXXXXXXXX` || exit 1

top -p $PG_PROC,$PGLOG,$PGWRT,$PGSTB,$PGSTC,$PGD1,$PGD2,$PGD3 -n 1 -b | tail -9 | head -8 > $TEMPFILE

LINE=`head -1 $TEMPFILE`
PGMPC=`echo $LINE | awk '{ print $9}'`
PGMPM=`echo $LINE | awk '{ print $10}'`

LINE=`head -2 $TEMPFILE | tail -1`
PGLPC=`echo $LINE | awk '{ print $9}'`
PGLPM=`echo $LINE | awk '{ print $10}'`

LINE=`head -3 $TEMPFILE | tail -1`
PGWPC=`echo $LINE | awk '{ print $9}'`
PGWPM=`echo $LINE | awk '{ print $10}'`

LINE=`head -4 $TEMPFILE | tail -1`
PGSBPC=`echo $LINE | awk '{ print $9}'`
PGSBPM=`echo $LINE | awk '{ print $10}'`

LINE=`head -5 $TEMPFILE | tail -1`
PGSCPC=`echo $LINE | awk '{ print $9}'`
PGSCPM=`echo $LINE | awk '{ print $10}'`

LINE=`head -6 $TEMPFILE | tail -1`
PGD1PC=`echo $LINE | awk '{ print $9}'`
PGD1PM=`echo $LINE | awk '{ print $10}'`

LINE=`head -7 $TEMPFILE | tail -1`
PGD2PC=`echo $LINE | awk '{ print $9}'`
PGD2PM=`echo $LINE | awk '{ print $10}'`

LINE=`tail -1 $TEMPFILE`
PGD3PC=`echo $LINE | awk '{ print $9}'`
PGD3PM=`echo $LINE | awk '{ print $10}'`

rm -f $TEMPFILE

PERFDATA="|pgmpc=$PGMPC;pgmpm=$PGMPM;pglpc=$PGLPC;pglpm=$PGLPM;pgwpc=$PGWPC;pgwpm=$PGWPM;pgsbpc=$PGSBPC;pgsbpm=$PGSBPM;pgscpc=$PGSCPC;pgscpm=$PGSCPM;pgd1pc=$PGD1PC;pgd1pm=$PGD1PM;pgd2pc=$PGD2PC;pgd2pm=$PGD2PM;pgd3pc=$PGD3PC;pgd3pm=$PGD3PM"

if [ $CRITICAL_CPU ] ; then
    BCRES=`echo "$PGMPC > $CRITICAL_CPU || $PGLPC > $CRITICAL_CPU ||  $PGWPC > $CRITICAL_CPU ||  $PGSBPC > $CRITICAL_CPU ||  $PGSCPC > $CRITICAL_CPU ||  $PGD1PC > $CRITICAL_CPU ||  $PGD2PC > $CRITICAL_CPU ||  $PGD3PC > $CRITICAL_CPU" | bc`
    if [ $BCRES -ne 0 ] ; then
	echo "CRITICAL - %CPU ($PGMPC,$PGLPC,$PGWPC,$PGSBPC,$PGSCPC,$PGD1PC,$PGD2PC,$PGD3PC) greater than threshold of $CRITICAL_CPU$PERFDATA"
	exit $STATE_CRITICAL
    fi
fi

if [ $WARNING_CPU ] ; then
    BCRES=`echo "$PGMPC > $WARNING_CPU || $PGLPC > $WARNING_CPU ||  $PGWPC > $WARNING_CPU ||  $PGSBPC > $WARNING_CPU ||  $PGSCPC > $WARNING_CPU ||  $PGD1PC > $WARNING_CPU ||  $PGD2PC > $WARNING_CPU ||  $PGD3PC > $WARNING_CPU" | bc`
    if [ $BCRES -ne 0 ] ; then
	echo "WARNING - %CPU ($PGMPC,$PGLPC,$PGWPC,$PGSBPC,$PGSCPC,$PGD1PC,$PGD2PC,$PGD3PC) greater than threshold of $WARNING_CPU$PERFDATA"
	exit $STATE_WARNING
    fi
fi

if [ $CRITICAL_MEM ] ; then
    BCRES=`echo "$PGMPM > $CRITICAL_MEM || $PGLPM > $CRITICAL_MEM ||  $PGWPM > $CRITICAL_MEM ||  $PGSBPM > $CRITICAL_MEM ||  $PGSCPM > $CRITICAL_MEM ||  $PGD1PM > $CRITICAL_MEM ||  $PGD2PM > $CRITICAL_MEM ||  $PGD3PM > $CRITICAL_MEM" | bc`
    if [ $BCRES -ne 0 ] ; then
	echo "CRITICAL - %MEM ($PGMPM,$PGLPM,$PGWPM,$PGSBPM,$PGSCPM,$PGD1PM,$PGD2PM,$PGD3PM) greater than threshold of $CRITICAL_MEM$PERFDATA"
	exit $STATE_CRITICAL
    fi
fi
if [ $WARNING_MEM ] ; then
    BCRES=`echo "$PGMPM > $WARNING_MEM || $PGLPM > $WARNING_MEM ||  $PGWPM > $WARNING_MEM ||  $PGSBPM > $WARNING_MEM ||  $PGSCPM > $WARNING_MEM ||  $PGD1PM > $WARNING_MEM ||  $PGD2PM > $WARNING_MEM ||  $PGD3PM > $WARNING_MEM" | bc`
    if [ $BCRES -ne 0 ] ; then
	echo "WARNING - %MEM ($PGMPM,$PGLPM,$PGWPM,$PGSBPM,$PGSCPM,$PGD1PM,$PGD2PM,$PGD3PM) greater than threshold of $WARNING_MEM$PERFDATA"
	exit $STATE_WARNING
    fi
fi

echo "OK - PostGreSQL - All processes are within parameters$PERFDATA"
exit $STATE_OK
