#!/bin/sh
# +------------------------------------------------------------------+
# |             ____ _               _        __  __ _  __           |
# |            / ___| |__   ___  ___| | __   |  \/  | |/ /           |
# |           | |   | '_ \ / _ \/ __| |/ /   | |\/| | ' /            |
# |           | |___| | | |  __/ (__|   <    | |  | | . \            |
# |            \____|_| |_|\___|\___|_|\_\___|_|  |_|_|\_\           |
# |                                                                  |
# | Copyright Mathias Kettner 2010             mk@mathias-kettner.de |
# +------------------------------------------------------------------+
#
# This file is part of Check_MK.
# The official homepage is at http://mathias-kettner.de/check_mk.
#
# check_mk is free software;  you can redistribute it and/or modify it
# under the  terms of the  GNU General Public License  as published by
# the Free Software Foundation in version 2.  check_mk is  distributed
# in the hope that it will be useful, but WITHOUT ANY WARRANTY;  with-
# out even the implied warranty of  MERCHANTABILITY  or  FITNESS FOR A
# PARTICULAR PURPOSE. See the  GNU General Public License for more de-
# ails.  You should have  received  a copy of the  GNU  General Public
# License along with GNU Make; see the file  COPYING.  If  not,  write
# to the Free Software Foundation, Inc., 51 Franklin St,  Fifth Floor,
# Boston, MA 02110-1301 USA.

# Check_MK agent plugin for monitoring ORACLE databases

# Get list of all running databases
SIDS=$(UNIX95=true ps ax -o args | sed -n '/^ora_pmon_\([^ ]*\)/s//\1/p')
if [ -z "$SIDS" ] ; then exit 0 ; fi

CACHE_MAXAGE=120

# Source the optional configuration file for this agent plugin
if [ -e "$MK_CONFDIR/mk_oracle.cfg" ]
then
    . $MK_CONFDIR/mk_oracle.cfg
fi

# It is possible to filter SIDS totally. Just add the following to
# the mk_oracle.cfg file:
#
#   EXCLUDE_<sid>="ALL"
#
# Another option is to filter single checks for SIDS. Just add
# lines as follows to the mk_oracle.cfg file. One service per
# line:
#
#   EXCLUDE_<sid>="<service>"
#
# For example skip oracle_sessions and oracle_logswitches checks
# for the instance "mysid".
#
#   EXCLUDE_mysid="oracle_sessions oracle_logswitches"
#
#
# This check uses a cache file to prevent problems with long running
# SQL queries. It starts building a cache when
#   a) no cache is present or the cache is too old and
#   b) the cache is not currently being built
# The cache is used for $CACHE_MAXAGE seconds. The CACHE_MAXAGE
# option is pre-set to 120 seconds but can be changed in mk_oracle.cfg.

for SID in $SIDS; do
    EXCLUDE=EXCLUDE_$SID
    EXCLUDE=${!EXCLUDE}
    # SID filtered totally?
    if [ "$EXCLUDE" = "ALL" ]; then
        continue
    fi

    CACHE_FILE=$MK_CONFDIR/oracle_$SID.cache

    # Check if file exists and recent enough
    if [ -s $CACHE_FILE ]; then
        NOW=$(date +%s)
        MTIME=$(stat -c %Y $CACHE_FILE)
        if [ $(($NOW - $MTIME)) -le $CACHE_MAXAGE ]; then
            USE_CACHE_FILE=1
        fi
    fi

    # If the cache file exists, output it, regardless of its age. If it's outdated
    # then it will be recreated *asynchronously*, we the new contents will not 
    # be available here anyway.
    if [ -s "$CACHE_FILE" ] ; then cat "$CACHE_FILE" ; fi

    # When not it checks if there is another task to update the cache is running
    # at the moment (*.new) file present.
    # When the cache is old and there is no *new file present, then start a query
    # to update the information for this instance.
    if [ -z "$USE_CACHE_FILE" -a ! -e "$CACHE_FILE.new" ]
    then
        setsid bash -c "
            set -o noclobber
            function sqlplus ()
            {
                OUTPUT=\$({ echo 'set pages 0' ; echo 'set lines 8000' ; echo 'set feedback off'; cat ; } | $MK_CONFDIR/sqlplus.sh \$1) || return 1
                echo \"\${OUTPUT}\" | sed -e 's/[[:space:]]\+/ /g' -e '/^[[:space:]]*$/d' -e \"s/^/\$1 /\"
            }

            {
            # Only execute checks when not filtered
            if [ "$EXCLUDE" = "${EXCLUDE/oracle_sessions/}" ]; then
                echo '<<<oracle_sessions>>>'
                echo \"select count(*) from v\\\$session where status = 'ACTIVE';\" | sqlplus \"$SID\"
            fi

            if [ "$EXCLUDE" = "${EXCLUDE/oracle_logswitches/}" ]; then
                echo '<<<oracle_logswitches>>>'
                echo \"select count(*) from v\\\$loghist where first_time > sysdate - 1/24;\" | sqlplus \"$SID\"
            fi

            if [ "$EXCLUDE" = "${EXCLUDE/oracle_tablespaces/}" ]; then
                echo '<<<oracle_tablespaces>>>'
                sqlplus "$SID" <<EOF | sed 's/READ ONLY/READONLY/g'
select f.file_name, f.tablespace_name, f.status, f.AUTOEXTENSIBLE, f.blocks, f.maxblocks,  f.USER_BLOCKS,  f.INCREMENT_BY, f.ONLINE_STATUS, t.BLOCK_SIZE, t.status from dba_data_files f, dba_tablespaces t where f.tablespace_name = t.tablespace_name
UNION
select f.file_name, f.tablespace_name, f.status, f.AUTOEXTENSIBLE, f.blocks, f.maxblocks,  f.USER_BLOCKS,  f.INCREMENT_BY, 'TEMP', t.BLOCK_SIZE, t.status from dba_temp_files f, dba_tablespaces t where f.tablespace_name = t.tablespace_name;
EOF
                fi
             } > $CACHE_FILE.new && mv $CACHE_FILE.new $CACHE_FILE || rm -f $CACHE_FILE*
        "
    fi
done
