Solaris ボリュームマネージャの管理

第25章 監視とエラーレポート (作業)

Solaris ボリュームマネージャは、スライスレベルの物理エラーのためにボリュームに書き込みできないなどの問題を検出すると、システム管理者に通知するためにボリュームの状態を変更します。 ただし、Solaris 管理コンソールを通じて Solaris ボリュームマネージャのグラフィカルユーザーインタフェースを使用したり、 metastat コマンドを実行してボリューム状態の変化を定期的にチェックしないと、状態の変化をタイムリーに把握することはできません。

この章では、Solaris ボリュームマネージャ SNMP エージェント (Solstice Enterprise AgentsTM 監視ソフトウェアのサブエージェント) など、Solaris ボリュームマネージャのさまざまな監視ツールについて説明します。 Solaris ボリュームマネージャ SNMP エージェントを設定して SNMP トラップを報告する方法の他にも、シェルスクリプトを作成して Solaris ボリュームマネージャのさまざまな機能を能動的に監視することができます。 このようなシェルスクリプトは cron ジョブとして動作し、潜在的な問題が顕在化する前にそれらを検出する上で役立ちます。

この章の内容は次のとおりです。

Solaris ボリュームマネージャの監視機能と報告機能 (作業マップ)

次の表に、Solaris ボリュームマネージャのエラーレポート機能を管理するのに必要な作業を示します。

作業 

説明 

参照先 

mdmonitord デーモンを設定してエラーを周期的にチェックする

/etc/rc2.d/S95svm.sync ファイルを編集して、mdmonitord デーモンが使用するエラーチェックの間隔を設定します。

「エラーを周期的にチェックするための mdmonitord デーモンの構成」

Solaris ボリュームマネージャ SNMP エージェントを構成する 

/etc/snmp/conf ディレクトリの構成ファイルを編集して、Solaris ボリュームマネージャが適切なシステムにトラップを送信できるようにします。

「Solaris ボリュームマネージャ SNMP エージェントの構成 」

cron コマンドでスクリプトを実行して Solaris ボリュームマネージャを監視する

エラーをチェックするスクリプトを作成または変更し、 cron コマンドでスクリプトを実行します。

cron ジョブによる Solaris ボリュームマネージャの監視 」

エラーを周期的にチェックするための mdmonitord デーモンの構成

Solaris ボリュームマネージャには、Solaris ボリュームマネージャボリュームのエラーをチェックする /usr/sbin/mdmonitord デーモンが含まれています。 デフォルトでは、このプログラムは、書き込みエラーなどにより、いずれかのボリュームでエラーが検出された場合にのみ、すべてのボリュームのエラーをチェックします。 ただし、指定の間隔でエラーを能動的にチェックするようにこのプログラムを設定することもできます。

Proceduremdmonitord コマンドを設定してエラーを周期的にチェックするには

/etc/rc2.d/S95svm.sync スクリプトは、起動時に mdmonitord コマンドを実行します。 /etc/rc2.d/S95svm.sync スクリプトを編集して、チェックする間隔を追加します。

手順
  1. スーパーユーザーになります。

  2. /etc/rc2.d/S95svm.sync スクリプトを編集し、mdmonitord コマンドで始まる行に - t フラグとチェックする間隔 (秒数) を指定します。


           if [ -x $MDMONITORD ]; then
                    $MDMONITORD -t 3600
                    error=$?
                    case $error in
                    0)      ;;
                    *)      echo "Could not start $MDMONITORD. Error $error."
                            ;;
                    esac
            fi
  3. mdmonitord コマンドを停止し、再起動して変更を有効にします。


    # /etc/rc2.d/S95svm.sync stop
    # /etc/rc2.d/S95svm.sync start
    

    詳細については、mdmonitord(1M) を参照してください。

Solaris ボリュームマネージャ SNMP エージェントの概要

Solaris ボリュームマネージャ SNMP トラップエージェントには、コアパッケージ SUNWlvmrSUNWlvma、それに Solstice Enterprise Agent パッケージが必要です。 必要なパッケージは、次のとおりです。

これらのパッケージは Solaris オペレーティングシステムの一部なので、パッケージの選択をインストール時に変更したり、最小限のパッケージ群だけをインストールしなければ、通常はデフォルトでインストールされます。 pkginfo pkgname コマンド (たとえば、pkginfo SUNWsasnx) を使って5つのパッケージが存在することを確認したら、次の各項の説明に従って Solaris ボリュームマネージャ SNMP エージェントを構成します。

Solaris ボリュームマネージャ SNMP エージェントの構成

Solaris ボリュームマネージャ SNMP エージェントはデフォルトでは有効にされていません。 SNMP トラップを有効にするには、次の手順を実行します。

おそらく、Solaris オペレーティングシステムをアップグレードするたびに、/etc/snmp/conf/enterprises.oid ファイルを編集し、その終わりに 手順1 の行を追加してから、Solaris Enterprise Agents サーバーの停止と再起動を行う必要があります。

この手順が終わると、SNMP トラップが、指定されたホストに送信されるようになります。 送信されたトラップを表示するためには、Solstice Enterprise Agents ソフトウェアなど、適切な SNMP モニターを使用する必要があります。

問題が発生したときにトラップを受信するためには、mdmonitord コマンドを設定してシステムを定期的にチェックする必要があります。 「エラーを周期的にチェックするための mdmonitord デーモンの構成」を参照してください。 また、その他のエラーチェックオプションについては、cron ジョブによる Solaris ボリュームマネージャの監視 」を参照してください。

ProcedureSolaris ボリュームマネージャ SNMP エージェントを構成するには

手順
  1. スーパーユーザーになります。

  2. /etc/snmp/conf/mdlogd.rsrc 構成ファイルを /etc/snmp/conf/mdlogd.rsrc に移動します。


    # mv /etc/snmp/conf/mdlogd.rsrc- /etc/snmp/conf/mdlogd.rsrc
    
  3. /etc/snmp/conf/mdlogd.acl ファイルを編集して、SNMP トラップをどのホストに送信するかを指定します。 次の部分を探してください。


            trap = {
                 {
                    trap-community = SNMP-trap
                    hosts = corsair
                    {
                        enterprise = "Solaris Volume Manager"
                        trap-num = 1, 2, 3
                    }

    hosts = corsair の行に、Solaris ボリュームマネージャ SNMP トラップの送信先ホストを指定します。 たとえば、SNMP トラップを lexicon に送信する場合は、この行を hosts = lexicon に変更します。 複数のホストを指定する場合は、hosts = lexicon, idiom のように、ホスト名をコンマで区切って指定します。

  4. 次に、/etc/snmp/conf/snmpdx.acl ファイルを編集して、SNMP トラップをどのホストに送信するかを指定します。

    trap = で始まるブロックを探し、ここに前の手順で指定したのと同じホスト名のリストを指定します。 このセクションは # でコメント文にされていることがあります。 その場合は、必要な行の始めにある # を取り除いてください。 このセクションでは他の行もコメント文にされている場合がありますが、それらの行はそのまま残しておいても、見やすくするために削除してもかまいません。 必要な行のコメントを解除し、ホスト名の行を変更した後のセクションは次のようになります。


    ###################
    # trap parameters #
    ###################
    
    trap = {
      {
            trap-community = SNMP-trap
            hosts =lexicon
            {
              enterprise = "sun"
              trap-num = 0, 1, 2-5, 6-16
            }
    #       {
    #         enterprise = "3Com"
    #         trap-num = 4
    #       }
    #       {
    #         enterprise = "snmp"
    #         trap-num = 0, 2, 5
    #       }
    #  }
    #  {
    #       trap-community = jerry-trap
    #       hosts = jerry, nanak, hubble
    #       {
    #         enterprise = "sun"
    #         trap-num = 1, 3
    #       }
    #       {
    #         enterprise = "snmp"
    #         trap-num = 1-3
    #       }
      }
    }

    /etc/snmp/conf/snmpdx.acl ファイルに同じ数の左括弧と右括弧があることを確認してください。


  5. 前の手順でコメントを解除した、/etc/snmp/conf/snmpdx.acl ファイルのセクションの中に新しい Solaris ボリュームマネージャセクションを追加します。


            trap-community = SNMP-trap
            hosts = lexicon
            {
              enterprise = "sun"
              trap-num = 0, 1, 2-5, 6-16
            }
            {
                enterprise = "Solaris Volume Manager"
                trap-num = 1, 2, 3
            }
    

    追加する 4 行は、enterprise = sun ブロックのすぐ後に挿入する必要があります。

  6. /etc/snmp/conf/enterprises.oid ファイルの最後に次の行を追加します。


    "Solaris Volume Manager"                           "1.3.6.1.4.1.42.104"
  7. Solstice Enterprise Agents サーバーを停止し、再起動します。


    # /etc/init.d/init.snmpdx stop
    # /etc/init.d/init.snmpdx start
    

Solaris ボリュームマネージャ SNMP エージェントの制約

Solaris ボリュームマネージャ SNMP エージェントには一定の制約があります。そのため、SNMP エージェントは、システム管理者が把握する必要がある、 Solaris ボリュームマネージャのすべての問題をトラップできるわけではありません。 具体的には、このエージェントは、次の場合にのみトラップを送信します。

RAID 0 ボリュームやソフトパーティションが定義されているディスクが使用不能な場合など、問題が発生しても、SNMP トラップが送信されない状況は少なくありません。これは、このデバイスに対する読み取りや書き込みが行われた場合でも同様です。 そのような場合、一般に SCSI や IDE のエラーは検出されますが、このようなエラーが監視コンソールに報告されるためには、他の SNMP エージェントがトラップを送信する必要があります。

cron ジョブによる Solaris ボリュームマネージャの監視

Procedureボリュームのエラーを自動的にチェックするには

手順

    Solaris ボリュームマネージャ構成のエラーを自動的にチェックするために、cron ユーティリティで定期的に実行できるスクリプトを作成します。

    次のスクリプト例は、必要に応じて変更することができます。


    このスクリプトは、Solaris ボリュームマネージャのエラーチェック機能を自動化するための基本的なスクリプトです。 独自の構成に合わせて変更する必要があります。


    #
    #ident "@(#)metacheck.sh   1.3     96/06/21 SMI"
    #!/bin/ksh
    #!/bin/ksh -x
    #!/bin/ksh -v
    # ident='%Z%%M%   %I%     %E% SMI'
    #
    # Copyright (c) 1999 by Sun Microsystems, Inc.
    #
    # metacheck
    #
    # メタデバイス構成の状態をチェックする。問題がある場合は、
    # ゼロ以外の終了コードを返す。オプションに応じて e メール通知を送信する。
    #
    # -h
    #	ヘルプ
    # -s setname
    #	チェックするセットを指定する。デフォルトでは「local」セットがチェックされる。
    # -m recipient [recipient...]
    #	指定された受信者に e メール通知を送信する。これは
    #	最後の引数でなければならない。この通知は簡単な e メールメッセージ
    #	として送信される。その件名は次のとおり。
    #		"Solaris Volume Manager Problem: metacheck.who.nodename.setname"
    #	これには、問題の要約と詳しい情報の入手方法が示されている。
    #	「setname」は -s オプションから、「who」は 
    #	-w オプションからそれぞれとられ、「nodename」は uname(1) によって報告される。
    #	e メール通知は次のオプションによっても影響される。
    #		-f	問題が検出された後の追加メッセージを抑制する
    #		-d	抑制を制御する
    #		-w	だれが e メールを生成したのかを示す
    #		-t	問題がないときでも e メールを強制的に送る
    # -w who
    #	だれがコマンドを実行しているのかを示す。デフォルトでは、これは
    #	id(1M) によって報告される user-name である。これは、
    #	e メール通知を送信する (-m) ときに使用される。
    # -f 
    #	フィルタ機能を有効にする。フィルタ機能は e メール通知 (-m) に適用される。
    #	フィルタ機能にはルート権限が必要。e メール通知を送信するときに、
    #	 /etc/lvm/metacheck.setname.pending ファイルを使って 
    #	フィルタを制御する。次のマトリクスは
    #	フィルタの動作を指定する。
    #
    #      問題の発見     ファイルあり
    #         yes             no                 ファイルを作成し、通知を送信する。
    #         yes             yes                現在の日付 (-d datefmt で指定された) が
    #                                            ファイルの日付と異なる場合は、
    #                                            通知を再び送信する。
    #         no              yes                ファイルを削除し、問題が解決したことを示す
    #                                            通知を送信する。
    #         no              no                 -t が指定されている場合は、通知を送信する。
    #	
    # -d datefmt
    #	フィルタ機能 (-f) の日付形式を指定する。このオプションは、
    #	e メールで通知を再送する頻度を制御する。 
    #	指定された形式 (strftime(3C)) に基づく現在の日付が
    #	/etc/lvm/metacheck.setname.pending ファイルに含まれている日付
    #	と同じなら、メッセージは抑制される。
    #	デフォルトの日付形式は「%D」で、通知を 1 日に 1 回再送する
    #	ことを意味する。
    # -t
    #	テストモード。問題がない場合でも、e メールの生成を有効にする。
    #	この機構や e メールアドレスを全体的に確認するときに使用する。
    #	
    #
    # 次のオプションは、メタチェックを crontab に組み込む。
    # たとえば、次の root crontab エントリがあるとする。
    #
    # 0,15,30,45 * * * * /usr/sbin/metacheck -f -w SVMcron \
    #   -d '\%D \%h' -m notice@example.com 2148357243.8333033@pager.example.com
    #
    # 15 分ごとに問題をチェックし、問題がある場合には、1 時間ごとに
    # e メールを notice@example.com 宛てに生成する (そして、e メール
    # ページャサービスに送信する)。crontab エントリの「%」文字の前にある \ に注意。
    # 戻ってくる e メールは root@nodename に返される。
    # 上の行によって生成される e メールメッセージの件名は次のようになる。
    # Solaris Volume Manager Problem: metacheck.SVMcron.nodename.local
    #
    
    # 制御端末にデバッグ行を表示する (一連のパイプとして動作)。
    decho()
    {
        if [ "$debug" = "yes" ] ; then
    	echo "DEBUG: $*"	 /dev/null> /dev/tty 2>1
        fi
    }
    
    # $1 文字列が $2-* に含まれる場合は $1 を返す。それ以外の場合は "" を返す。
    strstr()
    {
        typeset	look="$1"
        typeset	ret=""
    
        shift
    #   decho "strstr LOOK .$look. FIRST .$1."
        while [ $# -ne 0 ] ; do
    	if [ "$look" = "$1" ] ; then
    	    ret="$look"
    	fi
    	shift
        done
        echo "$ret"
    }
    
    # $1 文字列が $2-* に含まれる場合は、削除して結果を返す。
    strdstr()
    {
        typeset	look="$1"
        typeset	ret=""
    
        shift
    #   decho "strdstr LOOK .$look. FIRST .$1."
        while [ $# -ne 0 ] ; do
    	if [ "$look" != "$1" ] ; then
    	    ret="$ret $1"
    	fi
    	shift
        done
        echo "$ret"
    }
    
    merge_continued_lines()
    {
        awk -e '\
    	BEGIN { line = "";} \
    	$NF == "\\" { \
    	    $NF = ""; \
    	    line = line $0; \
    	    next; \
    	} \
    	$NF != "\\" { \
    	    if ( line != "" ) { \
    		print line $0; \
    		line = ""; \
    	    } else { \
    		print $0; \
    	    } \
    	}'
    }
    
    # メタデバイスと関係ない部分を破棄する。
    find_meta_devices()
    {
        typeset	devices=""
    
    #   decho "find_meta_devices .$*."
        while [ $# -ne 0 ] ; do
    	case $1 in
    	d+([0-9]) )	# メタデバイス名
    	    devices="$devices $1"
    	    ;;
    	esac
    	shift
        done
        echo "$devices"
    }
    
    # トップレベルのメタデバイスのリストを返す。
    toplevel()
    {
        typeset	comp_meta_devices=""
        typeset	top_meta_devices=""
        typeset	devices=""
        typeset	device=""
        typeset	comp=""
    
        metastat$setarg -p | merge_continued_lines | while read line ; do
    	echo "$line"
    	devices=find_meta_devices $line
    	set -- $devices
    	if [ $# -ne 0 ] ; then
    	    device=$1
    	    shift
    	    # デバイスがコンポーネントとしてすでに参照されているかチェックする。
    	    comp=strstr $device $comp_meta_devices
    	    if [ -z $comp ] ; then 
    		top_meta_devices="$top_meta_devices $device"
    	    fi
    	    # コンポーネントリストにコンポーネントを追加し、トップリストから削除する。
    	    while [ $# -ne 0 ] ; do
    		comp=$1
    		comp_meta_devices="$comp_meta_devices $comp"
    		top_meta_devices=strdstr $comp $top_meta_devices
    		shift
    	    done
    	fi
        done> /dev/null 2>1
        echo $top_meta_devices
    }
    
    #
    # - MAIN
    #
    METAPATH=/usr/sbin
    PATH=//usr/bin:$METAPATH
    USAGE="usage: metacheck [-s setname] [-h] [[-t] [-f [-d datefmt]] \
        [-w who] -m recipient [recipient...]]"
    
    datefmt="%D"
    debug="no"
    filter="no"
    mflag="no"
    set="local"
    setarg=""
    testarg="no"
    who=id | sed -e 's/^uid=[0-9][0-9]*(//' -e 's/).*//'
    
    while getopts d:Dfms:tw: flag
    do
        case $flag in
        d)	datefmt=$OPTARG;
    	;;
        D)	debug="yes"
    	;;
        f)	filter="yes"
    	;;
        m)	mflag="yes"
    	;;
        s)	set=$OPTARG;
    	if [ "$set" != "local" ] ; then
    		setarg=" -s $set";
    	fi
    	;;
        t)	testarg="yes";
    	;;
        w)	who=$OPTARG;
    	;;
        \?)	echo $USAGE
    	exit 1
    	;;
        esac
    done
    
    # mflag が指定されている場合は、他のすべての部分が受信者に属す。
    shift expr $OPTIND - 1
    if [ $mflag = "no" ] ; then
        if [ $# -ne 0 ] ; then 
    	echo $USAGE
    	exit 1
        fi
    else
        if [ $# -eq 0 ] ; then 
    	echo $USAGE
    	exit 1
        fi
    fi
    recipients="$*"
    
    curdate_filter=date +$datefmt
    curdate=date
    node=uname -n
    
    # ファイルを確立する。
    msg_f=/tmp/metacheck.msg.$$
    msgs_f=/tmp/metacheck.msgs.$$
    metastat_f=/tmp/metacheck.metastat.$$
    metadb_f=/tmp/metacheck.metadb.$$
    metahs_f=/tmp/metacheck.metahs.$$
    
    pending_f=/etc/lvm/metacheck.$set.pending 
    files="$metastat_f $metadb_f $metahs_f $msg_f $msgs_f"
    
    rm -f $files							> /dev/null 2>1
    trap "rm -f $files> /dev/null 2>1; exit 1" 1 2 3 15
    
    # metadb が動作可能かチェックする。
    have_metadb="yes"
    metadb$setarg 							> $metadb_f 2>1
    if [ $? -ne 0 ] ; then
        have_metadb="no"
    fi
    grep "there are no existing databases"  	 $metadb_f	> /dev/null 2>1
    if [ $? -eq 0 ] ; then
        have_metadb="no"
    fi
    grep "/dev/md/admin"				 $metadb_f	> /dev/null 2>1
    if [ $? -eq 0 ] ; then
        have_metadb="no"
    fi
    
    # metadb のアクセスに問題がないかチェックする。
    retval=0
    if [ "$have_metadb" = "no" ] ; then
        retval=1
        echo "metacheck: metadb problem, can't run '$METAPATH/metadb$setarg'" \
    								>> $msgs_f
    else
        # 状態のスナップショット
        metadb$setarg 2>1 | sed -e '1d' | merge_continued_lines	> $metadb_f
        metastat$setarg 2>1 | merge_continued_lines		> $metastat_f
        metahs$setarg -i 2>1 | merge_continued_lines		> $metahs_f
    
        #
        # 複製の問題をチェックする。フラグの中の大文字は
        # エラーを意味する。フィールドはタブで区切られる。
        #
        problem=awk  $metadb_f -F\t '{if ($1  /[A-Z]/) print $1;}'
        if [ -n "$problem" ] ; then
    	retval=expr $retval + 64
    	echo "\
    metacheck: metadb problem, for more detail run:\n\t$METAPATH/metadb$setarg -i" \
    								>> $msgs_f
        fi
    
        #
        # メタデバイスの状態をチェックする。
        #
        problem=awk  $metastat_f -e \
    		'/State:/ {if ($2 != "Okay"  $2 != "Resyncing") print $0;}'
        if [ -n "$problem" ] ; then
    	retval=expr $retval + 128
    	echo "\
    metacheck: metadevice problem, for more detail run:" \
    								>> $msgs_f
    
    	# 問題があるトップレベルメタデバイスへのメッセージの精度を高める。
    	top=toplevel
    	set -- $top
    	while [ $# -ne 0 ] ; do
    	    device=$1
    	    problem=metastat $device | awk -e \
    		'/State:/ {if ($2 != "Okay"  $2 != "Resyncing") print $0;}'
    	    if [ -n "$problem" ] ; then
    		echo "\t$METAPATH/metastat$setarg $device"	>> $msgs_f
    		# デバイスに何がマウントされているかを調べる。
    		mp=mount|awk -e '/\/dev\/md\/dsk\/'$device'[ \t]/{print $1;}'
    		if [ -n "$mp" ] ; then
    		    echo "\t\t$mp mounted on $device"		>> $msgs_f
    		fi
    	    fi
    	    shift
    	done
        fi
    
        #
        # ホットスペアが使用されているかチェックする。
        #
        problem=""
        grep "no hotspare pools found"	 $metahs_f		> /dev/null 2>1
        if [ $? -ne 0 ] ; then
    	problem=awk  $metahs_f -e \
    	    '/blocks/ { if ( $2 != "Available" ) print $0;}'
        fi
        if [ -n "$problem" ] ; then
    	retval=expr $retval + 256
    	echo "\
    metacheck: hot spare in use, for more detail run:\n\t$METAPATH/metahs$setarg -i" \
    								>> $msgs_f
        fi
    fi
    
    # エラーが発生している場合は、レポートを送信する。
    if [ $retval -ne 0 ] ; then
        if [ -n "$recipients" ] ; then 
    	re=""
    	if [ -f $pending_f ]  [ "$filter" = "yes" ] ; then
    	    re="Re:"
    	    # 保留された通知がある。日付をチェックして再送するか決める。
    	    penddate_filter=cat $pending_f | head -1
    	    if [ "$curdate_filter" != "$penddate_filter" ] ; then
    		rm -f $pending_f				> /dev/null 2>1
    	    else
    	 	if [ "$debug" = "yes" ] ; then
    		    echo "metacheck: email problem notification still pending"
    		    cat $pending_f
    		fi
    	    fi
    	fi
    	if [ ! -f $pending_f ] ; then
    	    if [ "$filter" = "yes" ] ; then
    		echo "$curdate_filter\n\tDate:$curdate\n\tTo:$recipients" \
    								> $pending_f
    	    fi
    	    echo "\
    Solaris Volume Manager: $node: metacheck$setarg: Report: $curdate"		>> $msg_f
    	    echo "\
    --------------------------------------------------------------">> $msg_f
    	    cat $msg_f $msgs_f | mailx -s \
    		"${re}Solaris Volume Manager Problem: metacheck.$who.$set.$node" $recipients
    	fi
        else
    	cat $msgs_f
        fi
    else
        # 問題は検出されていない。
        if [ -n "$recipients" ] ; then
    	# デフォルトでは、メールを送信しない。また、何も印刷しない。
    	echo "\
    Solaris Volume Manager: $node: metacheck$setarg: Report: $curdate"		>> $msg_f
    	echo "\
    --------------------------------------------------------------">> $msg_f
    	if [ -f $pending_f ]  [ "$filter" = "yes" ] ; then
    	    # 保留されたフィルタが存在する。削除し、OK を送信する。
    	    rm -f $pending_f					> /dev/null 2>1
    	    echo "Problem resolved"				>> $msg_f
    	    cat $msg_f | mailx -s \
    		"Re: Solaris Volume Manager Problem: metacheck.$who.$node.$set" $recipients
    	elif [ "$testarg" = "yes" ] ; then
    	    # テストのため、問題がなくても、毎回、メールを送信する。
    	    echo "Messaging test, no problems detected"		>> $msg_f
    	    cat $msg_f | mailx -s \
    		"Solaris Volume Manager Problem: metacheck.$who.$node.$set" $recipients
    	fi
        else
    	echo "metacheck: Okay"
        fi
    fi
    
    rm -f $files							> /dev/null 2>1

    cron ユーティリティを使ってスクリプトを起動する手順については、cron(1M) のマニュアルページを参照してください。