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