【Oracle Database】アラートログファイル チェックツール

普段 Oracle Database に関する業務を行っていて、あったらいいなと思ったので、
ふとアラートログファイルのチェックツールをシェルスクリプトで書いてみました。

# Oracle Database 対象バージョン
  11g全般
  12cR1
  12cR2では対応していません。
   ※オプションで入力された日時をスクリプト内でアラートログファイルのタイムスタンプで検索できるように変換しています。しかし、12cR1 までのタイムスタンプの書式が 12cR2 から大幅に変更されているため本スクリプトでは変換が出来ないため、非対応です。 

## 構成
   alertcheck.sh
   (大元のシェルスクリプト)
   ↓
   ↓呼びだし
   ↓
   checkAndResult.lib
   (オプションの入力値のチェックや結果の出力を行う関数をまとめたライブラリ)

## オプション

**オプションはダブルクオーテーションで囲んで下さい**

-d 日付検索を行う
   "YYYY/MM/DD HH24:MI" > 指定した日時分で検索されます。
   "YYYY/MM/DD HH24:" > 指定した日時で検索されます。
   "YYYY/MM/DD HH24" > 指定した日時で検索されます。
   "YYYY/MM/DD" > 指定した年月日で検索されます。

-k キーワード検索を行う
   "キーワード"　> 指定したキーワードが該当する行番号が出力されるので、対話形式で行番号を入力するとキーワードに該当する前後10行が出力されます。
前10行に満たない場合は先頭を出力開始行とし、後ろ10行に満たない場合は最終行を
出力終了行とします。

## 実行前に

alertcheck.sh 内の 23行目の 「export ALERTLOG=」に環境に合わせたアラートログファイルのフルパスを記載してください

## スクリプト

```alertcheck.sh
#!/bin/sh

# 関数ライブラリ読み込み
. ./checkAndResult.lib

# OPTIND を退避
export OPTIND_OLD=$OPTIND

# オプション d の値を格納する環境変数を初期化
export TMP_D=

# オプション k の値を格納する環境変数を初期化
export TMP_K=

# オプション
# -d : 検索日付
#      "YYYY/MM/DD"
#      "YYYY/MM/DD HH24"
#      "YYYY/MM/DD HH24:MI"
# -k : 検索キーワード

# 検索対象アラートログファイル
export ALERTLOG=<アラートログファイルのフルパス>

#オプション解析
# OPTS には -d や -k の直後の引数が入る
while getopts :d:k: OPT
do
    case ${OPT} in
        d) export TMP_D=${OPTARG} ;;
        k) export TMP_K=${OPTARG} ;;
        \?) echo "Usage: ${0} [-d date] | [-k keyword]";exit 1 ;;
    esac
done

# TMP_D と TMP_K が null でないかによって処理
if [ -n "${TMP_D}" ]; then
    if [ -n "${TMP_K}" ]; then
        echo "Syntax error: Only one option can be specified (-k or -d)"
        exit 1
    fi
    getDateResult "${TMP_D}" "${ALERTLOG}"
elif [ -n "${TMP_K}" ]; then
    getKeywordResult "${TMP_K}" "${ALERTLOG}"
fi

# OPTINDを初期化
export OPTIND=$OPTIND_OLD
```
```checkAndResult.lib
#!/bin/sh

# 日時検索開始点日時
export START_DATE=

# 日時検索終了点日時
export END_DATE=

# キーワード検索開始の行番号
export START_KEYWORD=

# キーワード検索終了の行番号
export END_KEYWORD=

# アラートログパス
export ALERTLOG=

# アラートログの行数
export LINE_COUNT=

# キーワード検索のヒット件数
export GREPCOUNT=

# 検索対象日時
export YEAR=
export MONTH=
export DAY=
export HH=
export MI=

# 入力日時変換
convertDate(){

    # 入力された日付を年-分まで cut する
    export YEAR=`echo ${1} | cut -c 1-4`
    export MONTH=`echo ${1} | cut -c 6-7`
    export DAY=`echo ${1} | cut -c 9-10`
    export HH=`echo ${1} | cut -c 12-13`
    export MI=`echo ${1} | cut -c 15-16`

    # 月を英字に変換
    case ${MONTH} in
        01) export MONTH=`echo ${MONTH} | sed -e 's/01/Jan/'` ;;
        02) export MONTH=`echo ${MONTH} | sed -e 's/02/Feb/'` ;;
        03) export MONTH=`echo ${MONTH} | sed -e 's/03/Mar/'` ;;
        04) export MONTH=`echo ${MONTH} | sed -e 's/04/Apr/'` ;;
        05) export MONTH=`echo ${MONTH} | sed -e 's/05/Mon/'` ;;
        06) export MONTH=`echo ${MONTH} | sed -e 's/06/Jun/'` ;;
        07) export MONTH=`echo ${MONTH} | sed -e 's/07/Jul/'` ;;
        08) export MONTH=`echo ${MONTH} | sed -e 's/08/Aug/'` ;;
        09) export MONTH=`echo ${MONTH} | sed -e 's/09/Sep/'` ;;
        10) export MONTH=`echo ${MONTH} | sed -e 's/10/Oct/'` ;;
        11) export MONTH=`echo ${MONTH} | sed -e 's/11/Nov/'` ;;
        12) export MONTH=`echo ${MONTH} | sed -e 's/12/Dec/'` ;;
    esac

}

# 日時検索
getDateResult(){

    # 検索情報
    echo "***************************"
    echo "AlertLogFile is \"${2}\""
    echo "SearchDay is \"${1}\""
    echo "***************************"
    echo ""

    # 入力日時の変換
    convertDate "${1}"

    # 入力日時の文字列長に応じ、処理
    # YYYY/MM/DD HH24:MI
    if [ ${#1} -eq 16 ] ; then
        export START_DATE=`grep ".*${MONTH} ${DAY} ${HH}:${MI}:.*${YEAR}" -n ${2} | sed -e 's/:.*//' | head -n 1`
        export END_DATE=`grep ".*${MONTH} ${DAY} ${HH}:${MI}:.*${YEAR}" -n ${2} | sed -e 's/:.*//' | tail -n 1`
        cat ${2} | sed -n "${START_DATE},${END_DATE}p" 2> /dev/null
    # YYYY/MM/DD HH24
    elif [ ${#1} -eq 13 ] || [ ${#1} -eq 14 ] ; then
        export START_DATE=`grep ".*${MONTH} ${DAY} ${HH}:.*${YEAR}" -n ${2} | sed -e 's/:.*//' | head -n 1`
        export END_DATE=`grep ".*${MONTH} ${DAY} ${HH}:.*${YEAR}" -n ${2} | sed -e 's/:.*//' | tail -n 1`
        cat ${2} | sed -n "${START_DATE},${END_DATE}p" 2> /dev/null
    # YYYY/MM/DD
    elif [ ${#1} -eq 10 ] ; then
        export START_DATE=`grep ".*${MONTH} ${DAY} .*${YEAR}" -n ${2} | sed -e 's/:.*//' | head -n 1`
        export END_DATE=`grep ".*${MONTH} ${DAY} .*${YEAR}" -n ${2} | sed -e 's/:.*//' | tail -n 1`
        cat ${2} | sed -n "${START_DATE},${END_DATE}p" 2> /dev/null
    fi

    if [ $? -ne 0 ] ; then
       echo "Result is none"
    fi

}

# 検索対象の行番号前後10行が妥当かチェックする

checkKeyword(){

    export LINE_COUNT=`cat ${ALERTLOG} | wc -l`
    #export START_KEYWORD=`expr ${ANSWER} - 10`
    #export END_KEYWORD=`expr ${ANSWER} + 10`

    if [ `expr ${ANSWER} - 10` -ge 10 ] ; then
        export START_KEYWORD=`expr ${ANSWER} - 10`
        if [ `expr ${ANSWER} + 10` -le ${LINE_COUNT} ] ; then
            export END_KEYWORD=`expr ${ANSWER} + 10`
        elif [ `expr ${ANSWER} + 10` -gt ${LINE_COUNT} ] ; then
            export END_KEYWORD=${LINE_COUNT}
        fi
    elif [ `expr ${ANSWER} - 10` -lt 10 ] ; then
        export START_KEYWORD=1
        if [ `expr ${ANSWER} + 10` -le ${LINE_COUNT} ] ; then
            export END_KEYWORD=`expr ${ANSWER} + 10`
        elif [ `expr ${ANSWER} + 10` -gt ${LINE_COUNT} ] ; then
            export END_KEYWORD=${LINE_COUNT}
        fi
    fi

}

# キーワード検索
getKeywordResult(){

    # 引数より渡されたアラートログを変数に格納
    export ALERTLOG=${2}
    # 検索情報
    echo "***************************"
    echo "AlertLogFile is \"${2}\""
    echo "KeyWord is \"${1}\""
    echo "***************************"
    echo ""
    
    export GREPCOUNT=`grep ".*${1}.*" -n ${2} | sed -e 's/:.*//' | wc -l`
    if [ ${GREPCOUNT} -gt 0 ] ; then
    echo "ヒット行番号"
    grep ".*${1}.*" -n ${2} | sed -e 's/:.*//'
    else
    echo "Result is none"
    exit 1
    fi

    echo ""
    echo "${1} に該当する行番号を表示しました"
    echo "検索したい行番号を入力してください"

    read ANSWER

    echo ""
    echo "検索対象の行番号前後10行を表示します"

    # キーワード行数チェック
    checkKeyword

    # 出力
    cat ${2} | sed -n "${START_KEYWORD},${END_KEYWORD}p"  2> /dev/null

}
```

## 実行結果

**-d "YYYY/MM/DD HH24:MI" 指定時**
[oracle@ora190 ~]$ ./alertcheck.sh -d "2017/09/05 07:35"
\***************************
AlertLogFile is "/u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log"
SearchDay is "2017/09/05 07:35"
\***************************

Tue Sep 05 07:35:12 2017
Starting ORACLE instance (normal) (OS id: 2197)
Tue Sep 05 07:35:13 2017
CLI notifier numLatches:3 maxDescs:519
Tue Sep 05 07:35:13 2017
Due to limited space in shared pool (need 6094848 bytes, have 4194112 bytes), limiting Resource Manager entities from 2048 to 32
Tue Sep 05 07:35:13 2017
\**********************************************************************
Tue Sep 05 07:35:13 2017
Dump of system resources acquired for SHARED GLOBAL AREA (SGA)

Tue Sep 05 07:35:13 2017
 Per process system memlock (soft) limit = 64K
Tue Sep 05 07:35:13 2017
 Expected per process system memlock (soft) limit to lock
 SHARED GLOBAL AREA (SGA) into memory: 440M
:
:
:

**-d "YYYY/MM/DD HH24:" 指定時**
[oracle@ora190 ~]$ ./alertcheck.sh -d "2017/09/05 07:"
\***************************
AlertLogFile is "/u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log"
SearchDay is "2017/09/05 07:"
\***************************

Tue Sep 05 07:35:12 2017
Starting ORACLE instance (normal) (OS id: 2197)
Tue Sep 05 07:35:13 2017
CLI notifier numLatches:3 maxDescs:519
Tue Sep 05 07:35:13 2017
Due to limited space in shared pool (need 6094848 bytes, have 4194112 bytes), limiting Resource Manager entities from 2048 to 32
Tue Sep 05 07:35:13 2017
\**********************************************************************
Tue Sep 05 07:35:13 2017
Dump of system resources acquired for SHARED GLOBAL AREA (SGA)

Tue Sep 05 07:35:13 2017
 Per process system memlock (soft) limit = 64K
Tue Sep 05 07:35:13 2017
 Expected per process system memlock (soft) limit to lock
 SHARED GLOBAL AREA (SGA) into memory: 440M
Tue Sep 05 07:35:13 2017
 Available system pagesizes:
  4K, 2048K
Tue Sep 05 07:35:13 2017
 Supported system pagesize(s):
Tue Sep 05 07:35:13 2017
  PAGESIZE  AVAILABLE_PAGES  EXPECTED_PAGES  ALLOCATED_PAGES  ERROR(s)
Tue Sep 05 07:35:13 2017
        4K       Configured          112643          112643        NONE
Tue Sep 05 07:35:13 2017
 Reason for not supporting certain system pagesizes:
Tue Sep 05 07:35:13 2017
  2048K - Dynamic allocate and free memory regions
:
:
:

**-d "YYYY/MM/DD" 指定時**
[oracle@ora190 ~]$ ./alertcheck.sh -d "2017/09/05"
\***************************
AlertLogFile is "/u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log"
SearchDay is "2017/09/05"
\***************************

Tue Sep 05 07:35:12 2017
Starting ORACLE instance (normal) (OS id: 2197)
Tue Sep 05 07:35:13 2017
CLI notifier numLatches:3 maxDescs:519
Tue Sep 05 07:35:13 2017
Due to limited space in shared pool (need 6094848 bytes, have 4194112 bytes), limiting Resource Manager entities from 2048 to 32
Tue Sep 05 07:35:13 2017
\**********************************************************************
Tue Sep 05 07:35:13 2017
Dump of system resources acquired for SHARED GLOBAL AREA (SGA)

Tue Sep 05 07:35:13 2017
 Per process system memlock (soft) limit = 64K
Tue Sep 05 07:35:13 2017
 Expected per process system memlock (soft) limit to lock
 SHARED GLOBAL AREA (SGA) into memory: 440M
Tue Sep 05 07:35:13 2017
 Available system pagesizes:
  4K, 2048K
Tue Sep 05 07:35:13 2017
 Supported system pagesize(s):
Tue Sep 05 07:35:13 2017
  PAGESIZE  AVAILABLE_PAGES  EXPECTED_PAGES  ALLOCATED_PAGES  ERROR(s)
Tue Sep 05 07:35:13 2017
        4K       Configured          112643          112643        NONE
Tue Sep 05 07:35:13 2017
 Reason for not supporting certain system pagesizes:
:
:
:

**-k "ORA-00312" 指定時**
[oracle@ora190 ~]$ ./alertcheck.sh -k "ORA-00312"
\***************************
AlertLogFile is "/u01/app/oracle/diag/rdbms/orcl/orcl/trace/alert_orcl.log"
KeyWord is "ORA-00312"
\***************************

ヒット行番号
865
869
876
880
890

ORA-00312 に該当する行番号を表示しました
検索したい行番号を入力してください
865 <- 入力

検索対象の行番号前後10行を表示します
Stopping Emon pool
Sat Dec 19 17:12:01 2015
ALTER SYSTEM enable restricted session;
alter database "orcl" open resetlogs
Sat Dec 19 17:12:01 2015
MMNL started with pid=19, OS id=31534
RESETLOGS after incomplete recovery UNTIL CHANGE 1594142 time 07/07/2014 07:05:17
Sat Dec 19 17:12:02 2015
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_31526.trc:
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/u01/app/oracle/oradata/orcl/redo_b/redo1_b.rdo'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
ORA-00312: online log 1 thread 1: '/u01/app/oracle/oradata/orcl/redo_a/redo1_a.rdo'
ORA-27037: unable to obtain file status
Linux-x86_64 Error: 2: No such file or directory
Additional information: 3
Sat Dec 19 17:12:02 2015
Errors in file /u01/app/oracle/diag/rdbms/orcl/orcl/trace/orcl_ora_31526.trc:
ORA-00313: open failed for members of log group 1 of thread 1