サービス監視 - 内部監視

  内部監視用の処理は必要なプロセスが稼動しているかどうかの確認しか行わないので対象サーバにて定期的に実行する。

  (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で定期的に実行するなどの工夫が必要かも。。


トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-06-11 (木) 00:48:50 (5426d)