#! /bin/sh
#
# Log file pattern detector plugin for Nagios
# Written by Ethan Galstad (nagios@nagios.org)
# Last Modified: 07-31-1999

# Updated by John Daily (jdaily@apparatus.net)
# Last Modified: August 2006

# Usage: ./check_log -F <log_file> -O <old_log_file> -b <pattern> -f <pattern>
#        -F    Specify the log to scan
#        -O    Specify a location/filename for the script to create a
#              copy of the log.  That path plus an extension will also
#              be used to maintain error states between runs.
#        -b    Specify the "broken" pattern to watch for in the log.
#        -f    Specify the "fixed" pattern to watch for in the log.
#
# Once the script sees an error, it will remain in an error state until
# the the "fixed" pattern shows up (or until the .err file it creates
# is removed).


# Paths to commands used in this script.  These
# may have to be modified to match your system setup.

PATH=""

ECHO="/bin/echo"

# Allow for extended REs   -jd
GREP="/bin/egrep"
CUT="/bin/cut"
DIFF="/usr/bin/diff"
TAIL="/usr/bin/tail"
CAT="/bin/cat"
RM="/bin/rm"

PROGNAME=`/bin/basename $0`

# Hard-coded - this script is in a non-standard location.  -jd
PROGPATH="/usr/lib/nagios/plugins"

REVISION=`echo '$Revision: 1.4 $' | /bin/sed -e 's/[^0-9.]//g'`

. $PROGPATH/utils.sh

print_usage() {
    echo "Usage: $PROGNAME -F logfile -O oldlog -b broken-regex -f fixed-regex"
    echo "Usage: $PROGNAME --help"
    echo "Usage: $PROGNAME --version"
}

print_help() {
    print_revision $PROGNAME $REVISION
    echo ""
    print_usage
    echo ""
    echo "Log file pattern detector plugin for Nagios"
    echo ""
    support
}

# Make sure the correct number of command line
# arguments have been supplied

if [ $# -lt 1 ]; then
    print_usage
    exit $STATE_UNKNOWN
fi

# Grab the command line arguments

#logfile=$1
#oldlog=$2
#query=$3
exitstatus=$STATE_WARNING #default
while test -n "$1"; do
    case "$1" in
        --help)
            print_help
            exit $STATE_OK
            ;;
        -h)
            print_help
            exit $STATE_OK
            ;;
        --version)
            print_revision $PROGNAME $VERSION
            exit $STATE_OK
            ;;
        -V)
            print_revision $PROGNAME $VERSION
            exit $STATE_OK
            ;;
        --filename)
            logfile=$2
            shift
            ;;
        -F)
            logfile=$2
            shift
            ;;
        --oldlog)
            oldlog=$2
            shift
            ;;
        -O)
            oldlog=$2
            shift
            ;;
        -b)
            brokenquery=$2
            shift
            ;;
        -f)
            fixedquery=$2
            shift
            ;;
        -x)
            exitstatus=$2
            shift
            ;;
        --exitstatus)
            exitstatus=$2
            shift
            ;;
        *)
            echo "Unknown argument: $1"
            print_usage
            exit $STATE_UNKNOWN
            ;;
    esac
    shift
done

# Check for required arguments
if [ ! $logfile ]; then
    echo "Missing argument: -F"
    print_usage
    exit $STATE_UNKNOWN
fi

if [ ! $oldlog ]; then
    echo "Missing argument: -O"
    print_usage
    exit $STATE_UNKNOWN
fi

if [ ! $fixedquery ]; then
    echo "Missing argument: -f"
    print_usage
    exit $STATE_UNKNOWN
fi

if [ ! $brokenquery ]; then
    echo "Missing argument: -b"
    print_usage
    exit $STATE_UNKNOWN
fi

# If the source log file doesn't exist, exit

if [ ! -e $logfile ]; then
    $ECHO "Log check error: Log file $logfile does not exist!\n"
    exit $STATE_UNKNOWN
elif [ ! -r $logfile ] ; then
    $ECHO "Log check error: Log file $logfile is not readable!\n"
    exit $STATE_UNKNOWN
fi

# If the old log file doesn't exist, this must be the first time
# we're running this test, so copy the original log file over to
# the old diff file and exit

if [ ! -e $oldlog ]; then
    $CAT $logfile > $oldlog
    $ECHO "Log check data initialized...\n"
    exit $STATE_OK
fi

# Determine whether we're already in an error state
status_file=$oldlog.err
previous_error=0

if [ -e $status_file ]; then
    previous_error=1
fi

# The old log file exists, so compare it to the original log now

# The temporary file that the script should use while
# processing the log file.
if [ -x /bin/mktemp ]; then
    tempdiff=`/bin/mktemp /tmp/check_log.XXXXXXXXXX`
else
    tempdiff=`/bin/date '+%H%M%S'`
    tempdiff="/tmp/check_log.${tempdiff}"
    /bin/touch $tempdiff
    chmod 600 $tempdiff
fi

$DIFF $logfile $oldlog > $tempdiff

# Count the number of matching log entries we have.  This count may
# not be terribly accurate; if we see fixed messages interpersed with
# broken messages, we have no way of reflecting that in the count.
count=`$GREP -c "$brokenquery" $tempdiff`

# Get the last matching entries in the diff file and compare line numbers
lastbroken=`$GREP -n "$brokenquery" $tempdiff | $TAIL --lines=1 `

lastbrokenentry=`$ECHO "$lastbroken" | $CUT -d : -f 1`
lastfixedentry=`$GREP -n "$fixedquery" $tempdiff | $TAIL --lines=1 | $CUT -d : -f 1`

lastbrokenentryline=`$ECHO "$lastbroken" | /bin/sed 's/^[0-9][0-9]*:< //'`

# If previous error is 1, we're still critical unless
# lastfixedentry > lastbrokenentry
if [ $previous_error -eq 1 ]; then
    exitstatus=$STATE_CRITICAL

    if [ ! -z $lastfixedentry ]; then
        if [ ! -z $lastbrokenentry ]; then
            if [ $lastfixedentry -gt $lastbrokenentry ]; then
                exitstatus=$STATE_OK
            fi
        else
            exitstatus=$STATE_OK
        fi
    fi
fi

if [ $previous_error -eq 0 ]; then
    exitstatus=$STATE_OK

    if [ ! -z $lastbrokenentry ]; then
        if [ ! -z $lastfixedentry ]; then
            if [ $lastbrokenentry -gt $lastfixedentry ]; then
                exitstatus=$STATE_CRITICAL
            fi
        else
            exitstatus=$STATE_CRITICAL
        fi
    fi
fi

if [ $previous_error -eq 0 -a $exitstatus -eq $STATE_CRITICAL ]; then
    /bin/touch $status_file
fi

if [ $previous_error -eq 1 -a $exitstatus -eq $STATE_OK ]; then
    /bin/rm $status_file
fi

$RM -f $tempdiff
$CAT $logfile > $oldlog

if [ $exitstatus -eq $STATE_OK ]; then
    if [ $previous_error -eq 0 ]; then
        $ECHO "Log check ok - 0 pattern matches found\n"
    else
        $ECHO "Log check ok - fixed pattern found\n"
    fi
else
    if [ $previous_error -eq 0 ]; then
        $ECHO "($count) $lastbrokenentryline\n"
    else
        $ECHO "No change in status\n"
    fi
fi

exit $exitstatus
