nix-config/ansible/roles/elnappo.check_mk_agent/files/plugins/mk_oracle.aix

1153 lines
44 KiB
Bash
Executable File

#!/bin/bash
# +------------------------------------------------------------------+
# | ____ _ _ __ __ _ __ |
# | / ___| |__ ___ ___| | __ | \/ | |/ / |
# | | | | '_ \ / _ \/ __| |/ / | |\/| | ' / |
# | | |___| | | | __/ (__| < | | | | . \ |
# | \____|_| |_|\___|\___|_|\_\___|_| |_|_|\_\ |
# | |
# | Copyright Mathias Kettner 2014 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-
# tails. 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
# This plugin is a result of the common work of Thorsten Bruhns
# and Mathias Kettner. Thorsten is responsible for the ORACLE
# stuff, Mathias for the shell hacking...
# Example for mk_oracle.cfg
# DBUSER=<DBUSER>:<PASSWORD>:<SYSDBA>:<HOSTNAME>:<Port>
# ASMUSER=<DBUSER>:<PASSWORD>:<SYSDBA/SYSASM>:<HOSTNAME>:<Port>
#
# SYSDBA or SYSASM is optional but needed for a mounted instance
# HOSTNAME is optional - Default is localhost
# PORT is optional - Default is 1521
while test $# -gt 0
do
if [ "${1}" = '-d' ] ; then
set -xv ; DEBUG=1
elif [ "${1}" = '-t' ] ; then
DEBUGCONNECT=1
fi
shift
done
if [ ! "$MK_CONFDIR" ] ; then
echo "MK_CONFDIR not set!" >&2
exit 1
fi
if [ ! "$MK_VARDIR" ] ; then
export MK_VARDIR=$MK_CONFDIR
fi
# .--Config--------------------------------------------------------------.
# | ____ __ _ |
# | / ___|___ _ __ / _(_) __ _ |
# | | | / _ \| '_ \| |_| |/ _` | |
# | | |__| (_) | | | | _| | (_| | |
# | \____\___/|_| |_|_| |_|\__, | |
# | |___/ |
# +----------------------------------------------------------------------+
# | The user can override and set variables in mk_oracle.cfg |
# '----------------------------------------------------------------------'
# Sections that run fast and do no caching
SYNC_SECTIONS="instance sessions logswitches undostat recovery_area processes recovery_status longactivesessions dataguard_stats performance locks"
# Sections that are run in the background and at a larger interval.
# Note: sections not listed in SYNC_SECTIONS or ASYNC_SECTIONS will not be
# executed at all!
ASYNC_SECTIONS="tablespaces rman jobs ts_quotas resumable"
# Sections that are run in the background and at a larger interval.
# Note: _ASM_ sections are only executed when SID starts with '+'
# sections listed in SYNC_SECTIONS or ASYNC_SECTIONS are not
# executed for ASM.
SYNC_ASM_SECTIONS="instance"
ASYNC_ASM_SECTIONS="asm_diskgroup"
# Interval for running async checks (in seconds)
CACHE_MAXAGE=600
# You can specify a list of SIDs to monitor. Those databases will
# only be handled, if they are found running, though!
#
# ONLY_SIDS="XE ORCL FOO BAR"
#
# It is possible to filter SIDS negatively. 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="sessions logswitches"
#
# Source the optional configuration file for this agent plugin
if [ -e "$MK_CONFDIR/mk_oracle.cfg" ]
then
. $MK_CONFDIR/mk_oracle.cfg
fi
#.
# .--SQL Queries---------------------------------------------------------.
# | ____ ___ _ ___ _ |
# | / ___| / _ \| | / _ \ _ _ ___ _ __(_) ___ ___ |
# | \___ \| | | | | | | | | | | |/ _ \ '__| |/ _ \/ __| |
# | ___) | |_| | |___ | |_| | |_| | __/ | | | __/\__ \ |
# | |____/ \__\_\_____| \__\_\\__,_|\___|_| |_|\___||___/ |
# | |
# +----------------------------------------------------------------------+
# | The following functions create SQL queries for ORACLE and output |
# | them to stdout. All queries output the database name or the instane |
# | name as first column. |
# '----------------------------------------------------------------------'
sql_performance()
{
if [ "$AT_LEAST_ORACLE_101" = 'yes' ] ; then
echo 'PROMPT <<<oracle_performance:sep(124)>>>'
echo "select upper(i.INSTANCE_NAME)
||'|'|| 'sys_time_model'
||'|'|| S.STAT_NAME
||'|'|| Round(s.value/1000000)
from v\$instance i,
v\$sys_time_model s
where s.stat_name in('DB time', 'DB CPU')
order by s.stat_name;
select upper(i.INSTANCE_NAME)
||'|'|| 'buffer_pool_statistics'
||'|'|| b.name
||'|'|| b.db_block_gets
||'|'|| b.db_block_change
||'|'|| b.consistent_gets
||'|'|| b.physical_reads
||'|'|| b.physical_writes
||'|'|| b.FREE_BUFFER_WAIT
||'|'|| b.BUFFER_BUSY_WAIT
from v\$instance i, V\$BUFFER_POOL_STATISTICS b;
select upper(i.INSTANCE_NAME)
||'|'|| 'librarycache'
||'|'|| b.namespace
||'|'|| b.gets
||'|'|| b.gethits
||'|'|| b.pins
||'|'|| b.pinhits
||'|'|| b.reloads
||'|'|| b.invalidations
from v\$instance i, V\$librarycache b;"
fi
}
sql_tablespaces()
{
echo 'PROMPT <<<oracle_tablespaces:sep(124)>>>'
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo "select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
|| '|' || file_name ||'|'|| tablespace_name ||'|'|| fstatus ||'|'|| AUTOEXTENSIBLE
||'|'|| blocks ||'|'|| maxblocks ||'|'|| USER_BLOCKS ||'|'|| INCREMENT_BY
||'|'|| ONLINE_STATUS ||'|'|| BLOCK_SIZE
||'|'|| decode(tstatus,'READ ONLY', 'READONLY', tstatus) || '|' || free_blocks
||'|'|| contents
from v\$database d , v\$instance i, (
select f.file_name, f.tablespace_name, f.status fstatus, f.AUTOEXTENSIBLE,
f.blocks, f.maxblocks, f.USER_BLOCKS, f.INCREMENT_BY,
f.ONLINE_STATUS, t.BLOCK_SIZE, t.status tstatus, nvl(sum(fs.blocks),0) free_blocks, t.contents
from dba_data_files f, dba_tablespaces t, dba_free_space fs
where f.tablespace_name = t.tablespace_name
and f.file_id = fs.file_id(+)
group by 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, t.contents
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, sum(sh.blocks_free) free_blocks, 'TEMPORARY'
from v\$thread th, dba_temp_files f, dba_tablespaces t, v\$temp_space_header sh
WHERE f.tablespace_name = t.tablespace_name and f.file_id = sh.file_id
GROUP BY th.instance, 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)
where d.database_role = 'PRIMARY';
"
elif [ "$AT_LEAST_ORACLE_92" = 'yes' ] ; then
echo "select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
|| '|' || file_name ||'|'|| tablespace_name ||'|'|| fstatus ||'|'|| AUTOEXTENSIBLE
||'|'|| blocks ||'|'|| maxblocks ||'|'|| USER_BLOCKS ||'|'|| INCREMENT_BY
||'|'|| ONLINE_STATUS ||'|'|| BLOCK_SIZE
||'|'|| decode(tstatus,'READ ONLY', 'READONLY', tstatus) || '|' || free_blocks
||'|'|| contents
from v\$database d , v\$instance i, (
select f.file_name, f.tablespace_name, f.status fstatus, f.AUTOEXTENSIBLE,
f.blocks, f.maxblocks, f.USER_BLOCKS, f.INCREMENT_BY,
'ONLINE' ONLINE_STATUS, t.BLOCK_SIZE, t.status tstatus, nvl(sum(fs.blocks),0) free_blocks, t.contents
from dba_data_files f, dba_tablespaces t, dba_free_space fs
where f.tablespace_name = t.tablespace_name
and f.file_id = fs.file_id(+)
group by f.file_name, f.tablespace_name, f.status, f.autoextensible,
f.blocks, f.maxblocks, f.user_blocks, f.increment_by, 'ONLINE',
t.block_size, t.status, t.contents
UNION
select f.file_name, f.tablespace_name, 'ONLINE' status, f.AUTOEXTENSIBLE,
f.blocks, f.maxblocks, f.USER_BLOCKS, f.INCREMENT_BY, 'TEMP',
t.BLOCK_SIZE, 'TEMP' status, sum(sh.blocks_free) free_blocks, 'TEMPORARY'
from v\$thread th, dba_temp_files f, dba_tablespaces t, v\$temp_space_header sh
WHERE f.tablespace_name = t.tablespace_name and f.file_id = sh.file_id
GROUP BY th.instance, f.file_name, f.tablespace_name, 'ONLINE',
f.autoextensible, f.blocks, f.maxblocks, f.user_blocks, f.increment_by,
'TEMP', t.block_size, t.status);
"
fi
}
sql_dataguard_stats()
{
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo 'PROMPT <<<oracle_dataguard_stats:sep(124)>>>'
echo "SELECT upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|'|| upper(d.DB_UNIQUE_NAME)
||'|'|| d.DATABASE_ROLE
||'|'|| ds.name
||'|'|| ds.value
FROM v\$database d
JOIN v\$parameter vp on 1=1
JOIN v\$instance i on 1=1
left outer join V\$dataguard_stats ds on 1=1
WHERE vp.name = 'log_archive_config'
AND vp.value is not null
ORDER BY 1;
"
fi
}
sql_recovery_status()
{
echo 'PROMPT <<<oracle_recovery_status:sep(124)>>>'
if [ "$AT_LEAST_ORACLE_101" = 'yes' ] ; then
echo "SELECT upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|'|| d.DB_UNIQUE_NAME
||'|'|| d.DATABASE_ROLE
||'|'|| d.open_mode
||'|'|| dh.file#
||'|'|| round((dh.CHECKPOINT_TIME-to_date('01.01.1970','dd.mm.yyyy'))*24*60*60)
||'|'|| round((sysdate-dh.CHECKPOINT_TIME)*24*60*60)
||'|'|| dh.STATUS
||'|'|| dh.RECOVER
||'|'|| dh.FUZZY
||'|'|| dh.CHECKPOINT_CHANGE#
FROM V\$datafile_header dh, v\$database d, v\$instance i
ORDER BY dh.file#;
"
elif [ "$AT_LEAST_ORACLE_92" = 'yes' ] ; then
echo "SELECT upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|'|| upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|'|| d.DATABASE_ROLE
||'|'|| d.open_mode
||'|'|| dh.file#
||'|'|| round((dh.CHECKPOINT_TIME-to_date('01.01.1970','dd.mm.yyyy'))*24*60*60)
||'|'|| round((sysdate-dh.CHECKPOINT_TIME)*24*60*60)
||'|'|| dh.STATUS
||'|'|| dh.RECOVER
||'|'|| dh.FUZZY
||'|'|| dh.CHECKPOINT_CHANGE#
FROM V\$datafile_header dh, v\$database d, v\$instance i
ORDER BY dh.file#;
"
fi
}
sql_rman()
{
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo 'PROMPT <<<oracle_rman:sep(124)>>>'
echo "select /*"$HINT_RMAN" check_mk rman1 */ upper(name)
|| '|'|| 'COMPLETED'
|| '|'|| to_char(COMPLETION_TIME, 'YYYY-mm-dd_HH24:MI:SS')
|| '|'|| to_char(COMPLETION_TIME, 'YYYY-mm-dd_HH24:MI:SS')
|| '|'|| case when INCREMENTAL_LEVEL IS NULL
then 'DB_FULL'
else 'DB_INCR'
end
|| '|'|| INCREMENTAL_LEVEL
|| '|'|| round(((sysdate-COMPLETION_TIME) * 24 * 60), 0)
|| '|'|| INCREMENTAL_CHANGE#
from (select upper(decode(${IGNORE_DB_NAME:-0}, 0, vd.NAME, i.instance_name)) name
, bd2.INCREMENTAL_LEVEL, bd2.INCREMENTAL_CHANGE#, min(bd2.COMPLETION_TIME) COMPLETION_TIME
from (select bd.file#, bd.INCREMENTAL_LEVEL, max(bd.COMPLETION_TIME) COMPLETION_TIME
from v\$backup_datafile bd
join v\$datafile_header dh on dh.file# = bd.file#
where dh.status = 'ONLINE'
group by bd.file#, bd.INCREMENTAL_LEVEL
) bd
join v\$backup_datafile bd2 on bd2.file# = bd.file#
and bd2.COMPLETION_TIME = bd.COMPLETION_TIME
join v\$database vd on vd.RESETLOGS_CHANGE# = bd2.RESETLOGS_CHANGE#
join v\$instance i on 1=1
group by upper(decode(${IGNORE_DB_NAME:-0}, 0, vd.NAME, i.instance_name))
, bd2.INCREMENTAL_LEVEL
, bd2.INCREMENTAL_CHANGE#
order by name, bd2.INCREMENTAL_LEVEL);
select /*"$HINT_RMAN" check_mk rman2 */ name
|| '|' || 'COMPLETED'
|| '|'
|| '|' || to_char(CHECKPOINT_TIME, 'yyyy-mm-dd_hh24:mi:ss')
|| '|' || 'CONTROLFILE'
|| '|'
|| '|' || round((sysdate - CHECKPOINT_TIME) * 24 * 60)
|| '|' || '0'
from (select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name)) name
,max(bcd.CHECKPOINT_TIME) CHECKPOINT_TIME
from v\$database d
join V\$BACKUP_CONTROLFILE_DETAILS bcd on d.RESETLOGS_CHANGE# = bcd.RESETLOGS_CHANGE#
join v\$instance i on 1=1
group by upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
);
select /*"$HINT_RMAN" check_mk rman3 */ name
|| '|COMPLETED'
|| '|'|| to_char(sysdate, 'YYYY-mm-dd_HH24:MI:SS')
|| '|'|| to_char(completed, 'YYYY-mm-dd_HH24:MI:SS')
|| '|ARCHIVELOG||'
|| round((sysdate - completed)*24*60,0)
|| '|'
from (
select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name)) name
, max(a.completion_time) completed
, case when a.backup_count > 0 then 1 else 0 end
from v\$archived_log a, v\$database d, v\$instance i
where a.backup_count > 0
and a.dest_id in
(select b.dest_id
from v\$archive_dest b
where b.target = 'PRIMARY'
and b.SCHEDULE = 'ACTIVE'
)
group by d.NAME, i.instance_name
, case when a.backup_count > 0 then 1 else 0 end);"
fi
}
sql_recovery_area()
{
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo 'PROMPT <<<oracle_recovery_area>>>'
echo "select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||' '|| round((SPACE_USED-SPACE_RECLAIMABLE)/
(CASE NVL(SPACE_LIMIT,1) WHEN 0 THEN 1 ELSE SPACE_LIMIT END)*100)
||' '|| round(SPACE_LIMIT/1024/1024)
||' '|| round(SPACE_USED/1024/1024)
||' '|| round(SPACE_RECLAIMABLE/1024/1024)
from V\$RECOVERY_FILE_DEST, v\$database d, v\$instance i;
"
fi
}
sql_undostat()
{
echo 'PROMPT <<<oracle_undostat:sep(124)>>>'
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo "select upper(i.INSTANCE_NAME)
||'|'|| ACTIVEBLKS
||'|'|| MAXCONCURRENCY
||'|'|| TUNED_UNDORETENTION
||'|'|| maxquerylen
||'|'|| NOSPACEERRCNT
from v\$instance i,
(select * from (select *
from v\$undostat order by end_time desc
)
where rownum = 1
and TUNED_UNDORETENTION > 0
);
"
elif [ "$AT_LEAST_ORACLE_92" = 'yes' ] ; then
# TUNED_UNDORETENTION and ACTIVEBLKS are not availibe in Oracle <=9.2!
# we sent a -1 for filtering in check_undostat
echo "select upper(i.INSTANCE_NAME)
||'|-1'
||'|'|| MAXCONCURRENCY
||'|-1'
||'|'|| maxquerylen
||'|'|| NOSPACEERRCNT
from v\$instance i,
(select * from (select *
from v\$undostat order by end_time desc
)
where rownum = 1
);
"
fi
}
sql_resumable()
{
echo 'PROMPT <<<oracle_resumable:sep(124)>>>'
echo "select upper(i.INSTANCE_NAME)
||'|'|| u.username
||'|'|| a.SESSION_ID
||'|'|| a.status
||'|'|| a.TIMEOUT
||'|'|| round((sysdate-to_date(a.SUSPEND_TIME,'mm/dd/yy hh24:mi:ss'))*24*60*60)
||'|'|| a.ERROR_NUMBER
||'|'|| to_char(to_date(a.SUSPEND_TIME, 'mm/dd/yy hh24:mi:ss'),'mm/dd/yy_hh24:mi:ss')
||'|'|| a.RESUME_TIME
||'|'|| a.ERROR_MSG
from dba_resumable a, v\$instance i, dba_users u
where a.INSTANCE_ID = i.INSTANCE_NUMBER
and u.user_id = a.user_id
and a.SUSPEND_TIME is not null
union all
select upper(i.INSTANCE_NAME)
|| '|||||||||'
from v\$instance i
;
"
}
sql_jobs()
{
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo 'PROMPT <<<oracle_jobs:sep(124)>>>'
echo "SELECT upper(decode(${IGNORE_DB_NAME:-0}, 0, vd.NAME, i.instance_name))
||'|'|| j.OWNER
||'|'|| j.JOB_NAME
||'|'|| j.STATE
||'|'|| ROUND((TRUNC(sysdate) + j.LAST_RUN_DURATION - TRUNC(sysdate)) * 86400)
||'|'|| j.RUN_COUNT
||'|'|| j.ENABLED
||'|'|| NVL(j.NEXT_RUN_DATE, to_date('1970-01-01', 'YYYY-mm-dd'))
||'|'|| NVL(j.SCHEDULE_NAME, '-')
||'|'|| jd.STATUS
FROM dba_scheduler_jobs j
join v\$database vd on 1 = 1
join v\$instance i on 1 = 1
left outer join (SELECT owner, job_name, max(LOG_ID) log_id
FROM dba_scheduler_job_run_details dd
group by owner, job_name
) jm on jm.JOB_NAME = j.JOB_NAME
and jm.owner=j.OWNER
left outer join dba_scheduler_job_run_details jd
on jd.owner = jm.OWNER
AND jd.JOB_NAME = jm.JOB_NAME
AND jd.LOG_ID = jm.LOG_ID;
"
fi
}
sql_ts_quotas()
{
echo 'PROMPT <<<oracle_ts_quotas:sep(124)>>>'
echo "select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|'|| Q.USERNAME
||'|'|| Q.TABLESPACE_NAME
||'|'|| Q.BYTES
||'|'|| Q.MAX_BYTES
from dba_ts_quotas Q, v\$database d, v\$instance i
where max_bytes > 0
union all
select upper(decode(${IGNORE_DB_NAME:-0}, 0, d.NAME, i.instance_name))
||'|||'
from v\$database d, v\$instance i
order by 1;
"
}
sql_version()
{
echo 'PROMPT <<<oracle_version>>>'
echo "select upper(i.INSTANCE_NAME)
|| ' ' || banner
from v\$version, v\$instance i
where banner like 'Oracle%';"
}
sql_instance()
{
echo 'prompt <<<oracle_instance:sep(124)>>>'
if [ ${ORACLE_SID:0:1} = '+' ] ; then
# ASM
echo "select upper(i.instance_name)
|| '|' || i.VERSION
|| '|' || i.STATUS
|| '|' || i.LOGINS
|| '|' || i.ARCHIVER
|| '|' || round((sysdate - i.startup_time) * 24*60*60)
|| '|' || '0'
|| '|' || 'NO'
|| '|' || 'ASM'
|| '|' || 'NO'
|| '|' || i.instance_name
from v\$instance i;
"
else
# normal Instance
echo "select upper(i.instance_name)
|| '|' || i.VERSION
|| '|' || i.STATUS
|| '|' || i.LOGINS
|| '|' || i.ARCHIVER
|| '|' || round((sysdate - i.startup_time) * 24*60*60)
|| '|' || DBID
|| '|' || LOG_MODE
|| '|' || DATABASE_ROLE
|| '|' || FORCE_LOGGING
|| '|' || d.name
from v\$instance i, v\$database d;
"
fi
}
sql_sessions()
{
echo 'prompt <<<oracle_sessions>>>'
echo "select upper(i.instance_name)
|| ' ' || CURRENT_UTILIZATION
from v\$resource_limit, v\$instance i
where RESOURCE_NAME = 'sessions';
"
}
sql_processes()
{
echo 'prompt <<<oracle_processes>>>'
echo "select upper(i.instance_name)
|| ' ' || CURRENT_UTILIZATION
|| ' ' || ltrim(rtrim(LIMIT_VALUE))
from v\$resource_limit, v\$instance i
where RESOURCE_NAME = 'processes';
"
}
sql_logswitches()
{
echo 'prompt <<<oracle_logswitches>>>'
echo "select upper(i.instance_name)
|| ' ' || logswitches
from v\$instance i ,
(select count(1) logswitches
from v\$loghist h , v\$instance i
where h.first_time > sysdate - 1/24
and h.thread# = i.instance_number
);
"
}
sql_locks()
{
if [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo 'prompt <<<oracle_locks:sep(124)>>>'
echo "select upper(i.instance_name)
|| '|' || b.sid
|| '|' || b.serial#
|| '|' || b.machine
|| '|' || b.program
|| '|' || b.process
|| '|' || b.osuser
|| '|' || b.username
|| '|' || b.SECONDS_IN_WAIT
|| '|' || b.BLOCKING_SESSION_STATUS
|| '|' || bs.inst_id
|| '|' || bs.sid
|| '|' || bs.serial#
|| '|' || bs.machine
|| '|' || bs.program
|| '|' || bs.process
|| '|' || bs.osuser
|| '|' || bs.username
from v\$session b
join v\$instance i on 1=1
join gv\$session bs on bs.inst_id = b.BLOCKING_INSTANCE
and bs.sid = b.BLOCKING_SESSION
where b.BLOCKING_SESSION is not null
;
select upper(i.instance_name)
|| '|||||||||||||||||'
from v\$instance i
;
"
fi
}
sql_locks_old()
{
if [ "$AT_LEAST_ORACLE_101" = 'yes' ] ; then
echo 'prompt <<<oracle_locks:sep(124)>>>'
echo "SET SERVEROUTPUT ON feedback off
DECLARE
type x is table of varchar2(20000) index by pls_integer;
xx x;
begin
begin
execute immediate 'select upper(i.instance_name)
|| ''|'' || a.sid
|| ''|'' || b.serial#
|| ''|'' || b.machine
|| ''|'' || b.program
|| ''|'' || b.process
|| ''|'' || b.osuser
|| ''|'' || a.ctime
|| ''|'' || decode(c.owner,NULL,''NULL'',c.owner)
|| ''|'' || decode(c.object_name,NULL,''NULL'',c.object_name)
from V\$LOCK a, v\$session b, dba_objects c, v\$instance i
where (a.id1, a.id2, a.type)
IN (SELECT id1, id2, type
FROM GV\$LOCK
WHERE request>0
)
and request=0
and a.sid = b.sid
and a.id1 = c.object_id (+)
union all
select upper(i.instance_name) || ''|||||||||''
from v\$instance i'
bulk collect into xx;
if xx.count >= 1 then
for i in 1 .. xx.count loop
dbms_output.put_line(xx(i));
end loop;
end if;
exception
when others then
for cur1 in (select upper(i.instance_name) instance_name from v\$instance i) loop
dbms_output.put_line(cur1.instance_name || '|||||||||'||sqlerrm);
end loop;
end;
END;
/
set serverout off
"
fi
}
sql_longactivesessions()
{
if [ "$AT_LEAST_ORACLE_101" = 'yes' ] ; then
echo 'prompt <<<oracle_longactivesessions:sep(124)>>>'
echo "select upper(i.instance_name)
|| '|' || s.sid
|| '|' || s.serial#
|| '|' || s.machine
|| '|' || s.process
|| '|' || s.osuser
|| '|' || s.program
|| '|' || s.last_call_et
|| '|' || s.sql_id
from v\$session s, v\$instance i
where s.status = 'ACTIVE'
and type != 'BACKGROUND'
and s.username is not null
and s.username not in('PUBLIC')
and s.last_call_et > 60*60
union all
select upper(i.instance_name)
|| '||||||||'
from v\$instance i;
"
fi
}
sql_asm_diskgroup()
{
echo 'prompt <<<oracle_asm_diskgroup>>>'
if [ "$AT_LEAST_ORACLE_112" = 'yes' ] ; then
echo "select STATE
|| ' ' || TYPE
|| ' ' || 'N'
|| ' ' || sector_size
|| ' ' || block_size
|| ' ' || allocation_unit_size
|| ' ' || total_mb
|| ' ' || free_mb
|| ' ' || required_mirror_free_mb
|| ' ' || usable_file_mb
|| ' ' || offline_disks
|| ' ' || voting_files
|| ' ' || name || '/'
from v\$asm_diskgroup;
"
elif [ "$AT_LEAST_ORACLE_102" = 'yes' ] ; then
echo "select STATE
|| ' ' || TYPE
|| ' ' || 'N'
|| ' ' || sector_size
|| ' ' || block_size
|| ' ' || allocation_unit_size
|| ' ' || total_mb
|| ' ' || free_mb
|| ' ' || required_mirror_free_mb
|| ' ' || usable_file_mb
|| ' ' || offline_disks
|| ' ' || 'N'
|| ' ' || name || '/'
from v\$asm_diskgroup;
"
fi
}
#.
# .--oraenv--------------------------------------------------------------.
# | |
# | ___ _ __ __ _ ___ _ ____ __ |
# | / _ \| '__/ _` |/ _ \ '_ \ \ / / |
# | | (_) | | | (_| | __/ | | \ V / |
# | \___/|_| \__,_|\___|_| |_|\_/ |
# | |
# +----------------------------------------------------------------------+
# | Functions for getting the Oracle environment |
# '----------------------------------------------------------------------'
function set_oraenv () {
ORACLE_SID=${1}
test -f /etc/oratab && ORATAB=/etc/oratab
# /var/opt/oracle/oratab is needed for Oracle Solaris
test -f /var/opt/oracle/oratab && ORATAB=/var/opt/oracle/oratab
test -f ${ORATAB:-""} || echo "ORA-99999 oratab not found"
test -f ${ORATAB:-""} || exit 1
ORACLE_HOME=$(cat ${ORATAB} | grep "^"${ORACLE_SID}":" | cut -d":" -f2)
if [ -z $ORACLE_HOME ] ; then
# cut last number from SID for Oracle RAC to find entry in oratab
ORACLE_SID_SHORT=$(echo $ORACLE_SID | sed "s/[0-9]$//")
ORACLE_HOME=$(cat ${ORATAB} | grep "^"${ORACLE_SID_SHORT}":" | cut -d":" -f2)
fi
LD_LIBRARY_PATH=$ORACLE_HOME/lib
if [ ! -d ${ORACLE_HOME:-"not_found"} ] ; then
echo "ORA-99999 ORACLE_HOME for ORACLE_SID="$ORACLE_SID" not found or not existing!"
exit 1
fi
TNS_ADMIN=${TNS_ADMIN:-$MK_CONFDIR}
test -f ${TNS_ADMIN}/sqlnet.ora || ( echo "ORA-99998 Couldn't find "${TNS_ADMIN}/sqlnet.ora ; exit 1)
export ORACLE_HOME TNS_ADMIN ORACLE_SID LD_LIBRARY_PATH
}
function get_oraversion () {
set_oraenv ${1}
ORACLE_VERSION=$($ORACLE_HOME/bin/sqlplus -V | grep ^SQL | cut -d" " -f3 | cut -d"." -f-2)
# remove possible existing variables
unset AT_LEAST_ORACLE_121 AT_LEAST_ORACLE_112 AT_LEAST_ORACLE_111 AT_LEAST_ORACLE_102 AT_LEAST_ORACLE_101 AT_LEAST_ORACLE_92
if [ "$ORACLE_VERSION" = '12.2' ] ; then
AT_LEAST_ORACLE_122=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' ] ; then
AT_LEAST_ORACLE_121=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' -o "$ORACLE_VERSION" = '11.2' ] ; then
AT_LEAST_ORACLE_112=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' -o "$ORACLE_VERSION" = '11.2' \
-o "$ORACLE_VERSION" = '11.1' ] ; then
AT_LEAST_ORACLE_111=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' -o "$ORACLE_VERSION" = '11.2' \
-o "$ORACLE_VERSION" = '11.1' -o "$ORACLE_VERSION" = '10.2' ] ; then
AT_LEAST_ORACLE_102=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' -o "$ORACLE_VERSION" = '11.2' \
-o "$ORACLE_VERSION" = '11.1' -o "$ORACLE_VERSION" = '10.2' \
-o "$ORACLE_VERSION" = '10.1' ] ; then
AT_LEAST_ORACLE_101=yes
fi
if [ "$ORACLE_VERSION" = '12.2' -o "$ORACLE_VERSION" = '12.1' -o "$ORACLE_VERSION" = '11.2' \
-o "$ORACLE_VERSION" = '11.1' -o "$ORACLE_VERSION" = '10.2' \
-o "$ORACLE_VERSION" = '10.1' -o "$ORACLE_VERSION" = '9.2' ] ; then
AT_LEAST_ORACLE_92=yes
fi
}
#.
# .--Functions-----------------------------------------------------------.
# | _____ _ _ |
# | | ___| _ _ __ ___| |_(_) ___ _ __ ___ |
# | | |_ | | | | '_ \ / __| __| |/ _ \| '_ \/ __| |
# | | _|| |_| | | | | (__| |_| | (_) | | | \__ \ |
# | |_| \__,_|_| |_|\___|\__|_|\___/|_| |_|___/ |
# | |
# +----------------------------------------------------------------------+
# | Helper functions |
# '----------------------------------------------------------------------'
function sqlplus_internal() {
loc_stdin=$(cat)
set_oraenv $SID
# reload mk_oracle.cfg for run_cached. Otherwise some variables are missing
if [ -e "$MK_CONFDIR/mk_oracle.cfg" ]
then
. $MK_CONFDIR/mk_oracle.cfg
fi
# mk_oracle_dbusers.conf is for compatibility. Do not use it anymore
ORACLE_USERCONF=${MK_CONFDIR}/mk_oracle_dbuser.conf
TNSPINGOK=no
if [ -f ${TNS_ADMIN}/tnsnames.ora ] ; then
if "${ORACLE_HOME}"/bin/tnsping "${ORACLE_SID}" >/dev/null 2>&1 ; then
TNSALIAS=$ORACLE_SID
TNSPINGOK=yes
fi
fi
ORADBUSER=""
DBPASSWORD=""
# ASM use '+' as 1st character in SID!
if [ ${ORACLE_SID:0:1} = '+' ] ; then
ORACFGLINE=${ASMUSER}
else
# use an individuel user or the default DBUSER from mk_oracle.cfg
dummy="DBUSER_"${ORACLE_SID}
ORACFGLINE=${!dummy}
if [ "$ORACFGLINE" = '' ] ; then
ORACFGLINE=${DBUSER}
fi
fi
if [ -f ${ORACLE_USERCONF} -a "${ORACFGLINE}" = '' ] ; then
# mk_oracle_dbuser.conf
ORACFGLINE=$(cat ${ORACLE_USERCONF} | grep "^"${ORACLE_SID}":")
# mk_oracle_dbuser has ORACLE_SID as 1. parameter. we need an offset for all values
offset=1
else
# mk_oracle.cfg
offset=0
fi
ORADBUSER=$(echo ${ORACFGLINE} | cut -d":" -f$[1+offset])
DBPASSWORD=$(echo ${ORACFGLINE} | cut -d":" -f$[2+offset])
DBSYSCONNECT=$(echo ${ORACFGLINE} | cut -d":" -f$[3+offset])
DBHOST=$(echo ${ORACFGLINE} | cut -d":" -f$[4+offset])
DBPORT=$(echo ${ORACFGLINE} | cut -d":" -f$[5+offset])
if [ ! "${ORACFGLINE}" ] ; then
# no configuration found
# => use the wallet with tnsnames.ora or EZCONNECT
TNSALIAS=${TNSALIAS:-"localhost:1521/${ORACLE_SID}"}
else
if [ ${DBSYSCONNECT} ] ; then
assysdbaconnect=" as "${DBSYSCONNECT}
fi
TNSALIAS=${TNSALIAS:-"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=${DBHOST:-"localhost"})(PORT=${DBPORT:-1521}))(CONNECT_DATA=(SID=${ORACLE_SID})(SERVER=DEDICATED)(UR=A)))"}
# ORADBUSER = '/'? => ignore DBPASSWORD and use the wallet
if [ "${ORADBUSER}" = '/' ] ; then
# connect with / and wallet
ORADBUSER=""
DBPASSWORD=""
if [ "$TNSPINGOK" = 'no' ] ; then
# create an EZCONNECT string when no tnsnames.ora is usable
# defaults to localhost:1521/<ORACLE_SID>
TNSALIAS="${DBHOST:-"localhost"}:${DBPORT:-1521}/${ORACLE_SID}"
fi
fi
fi
DBCONNECT="${ORADBUSER}/${DBPASSWORD}@${TNSALIAS}${assysdbaconnect}"
SQLPLUS=${ORACLE_HOME}/bin/sqlplus
if [ ! -x ${SQLPLUS} ] ; then
echo "sqlplus not found or ORACLE_HOME wrong! "
echo "SQLPLUS="${SQLPLUS}
return 1
fi
echo "$loc_stdin" | ${SQLPLUS} -L -s ${DBCONNECT}
if [ $? -ne 0 ] ; then
if [ "$DEBUGCONNECT" ] ; then
echo "Logindetails: ${DBCONNECT}" >&2
fi
return 1
fi
}
function ora_session_environment()
{
echo 'set pages 0 trimspool on feedback off lines 8000'
if [ "$AT_LEAST_ORACLE_102" = 'yes' -a ! "$DISABLE_ORA_SESSION_SETTINGS" ] ; then
echo 'set echo off'
echo 'alter session set "_optimizer_mjc_enabled"=false;'
# cursor_sharing is not valid for ASM instances
if [ ! ${ORACLE_SID:0:1} = '+' ] ; then
echo 'alter session set cursor_sharing=exact;'
fi
echo 'set echo on'
fi
echo 'whenever sqlerror exit 1'
echo ' '
}
# Helper function that calls an SQL statement with a clean output
# Usage: echo "..." | sqlplus SID
function sqlplus ()
{
local SID=$1
loc_stdin=$(cat)
loc_stdin=$(ora_session_environment)${loc_stdin}
# use sqlplus_internal when no sqlplus.sh is found
SQLPLUS="$MK_CONFDIR"/sqlplus.sh
test -f "$SQLPLUS" || SQLPLUS=sqlplus_internal
if OUTPUT=$(echo "$loc_stdin" | "$SQLPLUS" $SID)
then
echo "$OUTPUT"
else
echo '<<<oracle_instance:sep(124)>>>'
local SID_UPPER=$(echo "$SID" | tr '[:lower:]' '[:upper:]')
echo "$OUTPUT" | grep -v "^ERROR at line" | tr '\n' ' ' | sed "s/^/$SID_UPPER|FAILURE|/" ; echo
return 1
fi
}
function remove_excluded_sections ()
{
local sections="$1"
local excluded="$2"
local result=""
for section in $sections
do
local skip=
for exclude in $excluded
do
if [ "$exclude" = "$section" ] ; then
local skip=yes
break
fi
done
if [ "$skip" != yes ] ; then
result="$result $section"
fi
done
echo "$result"
}
# Create one SQL statements for several sections and run
# these with sqlplus. The exitcode is preserved.
function do_sync_checks ()
{
local SID=$1
local SECTIONS="$2"
for section in $SECTIONS
do
eval "sql_$section"
done | sqlplus $SID
}
function do_async_checks ()
{
local SID=$1
echo "$ASYNC_SQL" | sqlplus $SID
}
# Make sure that the new shell that is being run by run_cached inherits
# our functions
export -f sqlplus
export -f ora_session_environment
export -f sqlplus_internal
export -f do_async_checks
export -f set_oraenv
function file_mtime() {
/usr/bin/perl -e 'if (! -f $ARGV[0]){die "0000000"};$mtime=(stat($ARGV[0]))[9];print ($mtime);' "$1"
}
function run_cached_local () {
local section=
if [ "$1" = -s ] ; then local section="echo '<<<$2>>>' ; " ; shift ; fi
local NAME=$1
local MAXAGE=$2
shift 2
local CMDLINE="$section$@"
if [ ! -d $MK_VARDIR/cache ]; then mkdir -p $MK_VARDIR/cache ; fi
CACHEFILE="$MK_VARDIR/cache/$NAME.cache"
# Check if the creation of the cache takes suspiciously long and return
# nothing if the age (access time) of $CACHEFILE.new is twice the MAXAGE
local NOW=$(date +%s)
if [ -e "$CACHEFILE.new" ] ; then
CF_ATIME=$(file_mtime "$CACHEFILE.new")
if [ $((NOW - CF_ATIME)) -ge $((MAXAGE * 2)) ] ; then
# Kill the process still accessing that file in case
# it is still running. This avoids overlapping processes!
fuser -k -9 "$CACHEFILE.new" >/dev/null 2>&1
rm -f "$CACHEFILE.new"
return
fi
fi
# Check if cache file exists and is recent enough
if [ -s "$CACHEFILE" ] ; then
MTIME=$(file_mtime "$CACHEFILE")
if [ $((NOW - MTIME)) -le $MAXAGE ] ; then local USE_CACHEFILE=1 ; fi
# Output the file in any case, even if it is
# outdated. The new file will not yet be available
sed "/^<<</s/>>>$/:cached($MTIME,$MAXAGE)>>>/" "$CACHEFILE"
fi
# Cache file outdated and new job not yet running? Start it
if [ -z "$USE_CACHEFILE" -a ! -e "$CACHEFILE.new" ] ; then
if [ "$DEBUG" ] ; then
echo "set -o noclobber ; exec > \"$CACHEFILE.new\" || exit 1 ; $CMDLINE && mv \"$CACHEFILE.new\" \"$CACHEFILE\" || rm -f \"$CACHEFILE\" \"$CACHEFILE.new\"" | /bin/bash
else
# When the command fails, the output is throws away ignored
echo "set -o noclobber ; exec > \"$CACHEFILE.new\" || exit 1 ; $CMDLINE && mv \"$CACHEFILE.new\" \"$CACHEFILE\" || rm -f \"$CACHEFILE\" \"$CACHEFILE.new\"" | nohup /bin/bash >/dev/null 2>&1 &
fi
fi
}
#.
# .--Main----------------------------------------------------------------.
# | __ __ _ |
# | | \/ | __ _(_)_ __ |
# | | |\/| |/ _` | | '_ \ |
# | | | | | (_| | | | | | |
# | |_| |_|\__,_|_|_| |_| |
# | |
# +----------------------------------------------------------------------+
# | Iterate over all instances and execute sync and async sections. |
# '----------------------------------------------------------------------'
# Get list of all running databases
# Do not work on ASM in this plugin. => Ignore a running ASM-Instance!
SIDS=$(UNIX95=true ps -ef | awk '{print $NF}' | grep -E '^asm_pmon_|^ora_pmon_|^xe_pmon_XE' | cut -d"_" -f3-)
# If we do not have found any running database instance, then either
# no ORACLE is present on this system or it's just currently not running.
# In the later case we ouput empty agent sections so that Check_MK will be
# happy and execute the actual check functions.
if [ -z "$SIDS" -a ! -e "$MK_VARDIR/mk_oracle.found" ] ; then
exit
fi
# From now on we expect databases on this system (for ever)
touch $MK_VARDIR/mk_oracle.found
# Make sure that always all sections are present, even
# in case of an error. Note: the section <<<oracle_instance>>>
# section shows the general state of a database instance. If
# that section fails for an instance then all other sections
# do not contain valid data anyway.
for section in $SYNC_SECTIONS $ASYNC_SECTIONS $SYNC_ASM_SECTIONS $ASYNC_ASM_SECTIONS
do
echo "<<<oracle_"$section">>>"
done
for SID in $SIDS
do
# We need the SID in uppercase at later time
SID_UPPER=$(echo $SID | tr '[:lower:]' '[:upper:]')
# Check if SID is listed in ONLY_SIDS if this is used
if [ "$ONLY_SIDS" ] ; then
SKIP=yes
for S in $ONLY_SIDS ; do
if [ "$S" = "$SID" ] ; then
SKIP=
break
fi
done
if [ "$SKIP" ] ; then continue ; fi
fi
EXCLUDE=EXCLUDE_$SID
if [[ "$EXCLUDE" =~ ^[a-zA-Z][a-zA-Z0-9_]*$ ]]
then
# Handle explicit exclusion of instances
# but not for +ASM
EXCLUDE=${!EXCLUDE}
# SID filtered totally?
if [ "$EXCLUDE" = "ALL" ]; then
continue
fi
fi
if [ ${SID:0:1} = '+' ] ; then
DO_ASYNC_SECTIONS=${ASYNC_ASM_SECTIONS}
DO_SYNC_SECTIONS=${SYNC_ASM_SECTIONS}
else
# switch sections to ASM
DO_SYNC_SECTIONS=${SYNC_SECTIONS}
DO_ASYNC_SECTIONS=${ASYNC_SECTIONS}
fi
get_oraversion $SID
# Do sync checks
EXCLUDED=$(eval 'echo $EXCLUDE'"_$SID")
SECTIONS=$(remove_excluded_sections "$DO_SYNC_SECTIONS" "$EXCLUDED")
# Do async checks
ASECTIONS=$(remove_excluded_sections "$DO_ASYNC_SECTIONS" "$EXCLUDED")
ASYNC_SQL=$(for section in $ASECTIONS ; do eval "sql_$section" ; done)
export ASYNC_SQL
if [ "$DEBUGCONNECT" ] ; then
echo "-----------------------------------------------"
echo "Logincheck to Instance: "$SID" Version: "$ORACLE_VERSION
echo "select 'Login ok User: ' || user || ' on ' || host_name
from v\$instance;" | sqlplus $SID
echo "SYNC_SECTIONS=$SECTIONS"
echo "ASYNC_SECTIONS=$ASECTIONS"
if [ "$IGNORE_DB_NAME" ] ; then
echo "IGNORE_DB_NAME found. Ignoring DB_NAME in all SQLs!"
fi
if [ "$DISABLE_ORA_SESSION_SETTINGS" ] ; then
echo "Paramter DISABLE_ORA_SESSION_SETTINGS found!"
fi
if [ "$HINT_RMAN" ] ; then
echo "Using HINT_RMAN for this Instance!"
fi
# do not execute any check
continue
fi
do_sync_checks $SID "$SECTIONS"
run_cached_local oracle_$SID $CACHE_MAXAGE do_async_checks $SID
done