内部監視用の処理は必要なプロセスが稼動しているかどうかの確認しか行わないので対象サーバにて定期的に実行する。
(1) 以下のようなシェル(ファイル名:chk_proc)を作成する。 |
#!/bin/bash
#
# chkconfig: 345 99 01
# description: Process Check
# processname: chk_prc
#
### 設定 START ##############################
# このシェルの名前
own_name=`basename ${0}`
# 監視するプロセス(スペース区切り)
prc="httpd postmaster"
# ロードアベレージリミット(この値を超えたらメール通知)
high_avg=6.00
# チェック間隔(秒)
chk_range=120
# メール送信先
email_to_file="/xxxx/xxxx/ADMIN_MAIL"
# 送信者
email_from="svr-chk@example.com"
# このサーバの名前
server_name=`hostname -f`
# メール件名
subject="サーバ($server_name)内部監視"
# メール送信用プログラム
sendmail="/usr/sbin/sendmail"
#############################################
### 関数定義 START ##########################
## HELP表示
disp_help(){
echo "
使用法: `basename ${0}` start|stop
プロセス監視を開始/終了する
※監視するプロセスはスクリプト内に記述
また,停止したプロセスの再起動を試みます
"
}
## チェック処理中止
kill_prc(){
all_prc=`ps -A -l`
while [ $# -gt 0 ]
do
all_prc=`ps -A -l | grep $1`
chk_prc="$1
$all_prc"
kill_prc=`echo "$chk_prc" | awk '{
if(NR==1){
pid=$1;
} else {
if ($4==pid){
print $4" ";
}
if ($5==pid){
print $4" ";
}
}
}'`
kill -9 $kill_prc >/dev/null 2>&1
shift
done
}
## プロセス稼動チェック
chk_prc(){
while [ $# -gt 0 ]
do
count_prc $1
if [ "$prc_status" != "OK" ]; then
restart_prc $1
count_prc $1
if [ "$prc_status" != "OK" ]; then
err_status="STOP"
else
err_status="RESTART"
fi
else
err_status="START"
fi
err_status=$1":"$err_status
all_status=$all_status" "$err_status
shift
done
}
## プロセス数カウント
count_prc(){
prc_status="OK"
p_cnt=`ps -A | grep "$1" | wc -l`
if [ $p_cnt -lt 1 ]; then
prc_status="NG"
fi
}
## プロセス再起動
restart_prc(){
if [ -x "/etc/init.d/$1" ]; then
/etc/init.d/"$1" start >/dev/null 2>&1
fi
}
## ロードアベレージチェック
cnt_loadavg(){
err_status="OK"
avg_str=`uptime`
avg_str=`echo $avg_str | awk {'print $11;'}`
n_avg=`echo $avg_str | sed s/\.[0-9,]*$//g`
h_avg=`echo $high_avg | sed s/\.[0-9]*$//g`
if [ $n_avg -gt $h_avg ];then
err_status="NG"
fi
now_avg=`echo $avg_str | sed s/,.*$//g`
err_status="LoadAvg:"$err_status
all_status=$all_status" "$err_status
}
## メッセージ作成準備(プロセスエラー)
warning_mail(){
all_msg="監視日時:`date +%m/%d" "%T`
"
while [ $# -gt 0 ]
do
msg=""
proc=`echo $1 | sed s/:.*$//g`
status=`echo $1 | sed s/^.*://g`
if [ "$proc" == "LoadAvg" ]; then
if [ "$status" != "OK" ]; then
msg="ロードアベレージが"$high_avg"を超えています(現在:"$now_avg")"
else
msg="ロードアベレージは"$high_avg"以下です(現在:"$now_avg")"
fi
else
if [ "$status" == "START" ]; then
msg=$proc"プロセスが起動しました"
elif [ "$status" == "STOP" ]; then
msg=$proc"プロセスが停止しました"
elif [ "$status" == "RESTART" ]; then
msg=$proc"プロセスが停止した為,再起動しました"
fi
fi
all_msg="$all_msg"$msg"
"
shift
done
mail_send_prc "$all_msg"
}
## メール送信
function mail_send_prc(){
if [ "$1" != "" ]; then
email_to=`cat $email_to_file`
mail_msg=`echo "$1" | nkf -s`
subject=`echo "$subject" | nkf -j`
$sendmail -t <<_EOMAIL_
To: $email_to
From: $email_from
Subject: $subject
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Type: text/plain; charset=iso-2022-jp
$mail_msg
.
_EOMAIL_
fi
}
## サーバチェックメイン処理
server_chk_main (){
# 最初のチェックは5秒間ディレイ
sleep 5
pre_all_status=""
while [ ture ]
do
all_status=""
# ロードアベレージチェック
cnt_loadavg $h_avg
# プロセス稼動チェック
chk_prc $prc
# 状態変化時はメール送信
touch /tmp/pre_all_status
pre_all_status=`cat /tmp/pre_all_status`
if [ "$all_status" != "$pre_all_status" ]; then
warning_mail $all_status
fi
# エラー状態退避
echo "$all_status" > /tmp/pre_all_status
# n秒待機
sleep $chk_range
done
}
### 関数定義 END ############################
### メイン処理 START ########################
mode=""
# 引数取得
case $1 in
stop)
mode="stop"
;;
start)
mode="start"
;;
restart)
mode="start"
;;
*)
disp_help
exit 0
esac
# 引数が指定されていないときはHELPを表示して終了
if [ "$mode" == "" ]; then
disp_help
exit 0
fi
## 重複起動を回避
all_pid=`ps -A -l | grep $own_name`
edt_pid=`echo "$$
$all_pid"`
kill_pid=`echo "$edt_pid" | awk '{
if (NR == 1){
OWN=$1;
} else {
if ($4 != OWN){
if ($5 != OWN){
print $4" ";
}
}
}
}'`
if [ "$kill_pid" != "" ]; then
kill_prc $kill_pid
fi
if [ "$mode" != "start" ]; then
exit 0
fi
## チェック開始
server_chk_main &
### メイン処理 END ########################
|
[処理内容の補足]
・チェックを行う各プロセスの起動スクリプトを
プロセス名と同じ名前で作成しておく事により、
停止時に再起動を試みるようにしている。)
・この処理自体がチェック対象のプロセスよりも
先に起動しないようにする。
(一応、最初のチェック時は5秒間待ってから
チェックするようにはなっているが。。)
|
(2) 上記のシェルを /etc/init.d 以下に配置し、サービスとして初期起動するようにしておく。 |
# cp chk_proc /etc/init.d/
# chkconfig --add chk_prc
# chkconfig --level 345 chk_prc on
|
[補足]
・チェック処理自体が止まってしまった時の為に、
cronで定期的に実行するなどの工夫が必要かも。。
|