Oracleのプロセスが正常かどうか確認するシェルスクリプト | A Day In The Boy's Life

A Day In The Boy's Life

とあるエンジニアのとある1日のつぶやき。

LinuxネタではなくOracleネタではあるのですが。

運用開始後にDBが正常に動作しているか監視したいという要件はよくあったりしますので、サービス監視ネタとしてまとめてみたいと思います。

環境は、Oracle11.2.0(2ノードRAC構成)、RedHat6.2環境をベースに書いています。



Oracleのサービス監視をする


サービス監視の一環として、正常にDBが稼動しているかどうかを動作しているプロセスの個数で監視(いわゆるプロセス監視)するケースはよくありますが、Oracleは動作するプロセスが非常に多かったりしますし、サービスの動作確認用コマンドが用意されていたりするので、それを応用してシェルで自動チェックする仕組みを作ってみます。


利用するコマンドは、下記のcrsctlコマンドでリソースの状況を表示するオプションをつけて実行します。


$ crsctl stat res -t
--------------------------------------------------------------------------------
NAME           TARGET  STATE        SERVER                   STATE_DETAILS
--------------------------------------------------------------------------------
Local Resources
--------------------------------------------------------------------------------
ora.DG1_CTRL.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.DG2_DATA.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.DG3_ARCH.dg
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.LISTENER.lsnr
               ONLINE  ONLINE       oradb1
               ONLINE  ONLINE       oradb2
ora.asm
               ONLINE  ONLINE       oradb1                Started
               ONLINE  ONLINE       oradb2                Started
--- snip ---

--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.LISTENER_SCAN1.lsnr
      1        ONLINE  ONLINE       oradb1
ora.LISTENER_SCAN2.lsnr
      1        ONLINE  ONLINE       oradb2
ora.LISTENER_SCAN3.lsnr
      1        ONLINE  ONLINE       oradb2
ora.cvu
      1        ONLINE  ONLINE       oradb2
ora.oradb1.vip
      1        ONLINE  ONLINE       oradb1
ora.oradb2.vip
      1        ONLINE  ONLINE       oradb2
ora.oradb.db
      1        ONLINE  ONLINE       oradb1                Open
      2        ONLINE  ONLINE       oradb2                Open
--- snip ---


上記のように、このコマンドでリソースの状況が確認できるうえに、TARGET(しかるべき状態)とSTATE(現在の状態)が表示できるので、これを比較することでリソースの状況がチェックできそうです。


ただ、これは視覚的にすごく見やすいのですが、プログラムから見れば処理しにくい部分があるため、「-t」オプションを除いたコマンド実行結果を利用します。


$ crsctl stat res
NAME=ora.DG1_CTRL.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.DG2_DATA.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.DG3_ARCH.dg
TYPE=ora.diskgroup.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.LISTENER.lsnr
TYPE=ora.listener.type
TARGET=ONLINE             , ONLINE
STATE=ONLINE on oradb1, ONLINE on oradb2

NAME=ora.LISTENER_SCAN1.lsnr
TYPE=ora.scan_listener.type
TARGET=ONLINE
STATE=ONLINE on oradb1
--- snip ---


この結果だと、TARGETとSTATEの部分がカンマ区切りで取得できるのでスクリプト的に処理しやすかったりします。



Oracleのリソース状況をチェックするスクリプト


ということで、以下のようなcrsctlコマンド実行結果を解析するシェルスクリプトを書いてみました。


#!/bin/bash

# チェック対象のリソース一覧。SCAN系やVIP、CVUなどのリソースはどちらのノードが持っているか不明なため対象外
RESOURCES=("ora.DG1_CTRL.dg" "ora.DG2_DATA.dg" "ora.DG3_ARCH.dg" "ora.LISTENER.lsnr" "ora.asm" "ora.net1.network" "ora.ons" "ora.oradb.db")

# RAC対象ノード
RACNODES=("oradb1" "oradb2")

# CRSコマンド
CRSCHECK="/opt/app/11.2.0/grid/bin/crsctl check cluster"

# 実行ファイル名
FILENAME="${0##*/}"

# CRSが生きているかチェック
crsstat=`$CRSCHECK | grep "online" | wc -l`
if [ $crsstat -ne 3 ]
then
    logger -p err -t "${FILENAME}" "error: Cannot communicate with Cluster Ready Services"
    exit
fi

# リソースをチェックするコマンド
CRSCMD="/opt/app/11.2.0/grid/bin/crsctl stat res "

# 各リソースをチェック
for res in "${RESOURCES[@]}"
do
# crsctlコマンドを実行しSTATE行を抽出し=で分割して結果を受取る
    result=`$CRSCMD $res | grep "STATE=" | cut -d "=" -f2`
    for node in "${RACNODES[@]}"
    do
# HOST名が存在しないかONLINEでなければそのリソースは停止している可能性がある
        status=`echo $result | grep "$node"`
        if [ -z "$status" ]
        then
            logger -p err -t "${FILENAME}" "error:" $res "on" $node "is missing."
        fi
    done
done


やっていることは、crsctlコマンドの実行結果から監視対象のリソース(RESOURCES配列の中身)のTARGETとSTATEの中身を比較しており、異常があったときにsyslog経由でエラーメッセージを吐き出すというものです。

あとは、Cronとかで数分おきにシェルを実行してチェックするように動作させておけばよいかと思います。


シェルのコメントにも書いていますが、SCAN系やVIPのリソースはどっちのノードが持っているか起動の状況によりばらけたり、1ノードを意図的に落としたときにフェイルオーバーして片ノードによってしまうということがあって監視が難しいので対象外にしています。

Oracle自身もリソースやプロセスに異常があったら自己修復するような機能を備えているので、この辺が完全にアウトになることがあるのか不明ではありますが。


あと、RAC用と書きましたが、対象リソース(RESOURCES変数)や対象ノード(RACNODES変数)を書き換えればSingle環境のOracleでもチェックは可能だと思います。

同様にcrsctlコマンドは利用できるので。


監視としては、syslogにメッセージが吐き出されるので、最終的にはログ監視の中で異常を拾う仕組みにはなっていますが、監視ツールのPandoraとかではスクリプトの実行結果を元に判別できたりもするので、ログに書き出す部分に戻り値を書いてあげてもよいかもしれません。