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) のマニュアルページを参照してください。