サービス監視 - 外部監視

  外部監視は「WEBアプリとして外部から利用可能か」を監視するので、監視処理自体は対象サーバのあるネットワーク外に設置する。
  ※監視処理への応答用の処理は対象サーバに設置しておく。
  ※httpリクエストの結果からサーバ状態を判断するので余計なポートを空けたりしなくてもよい。

  (1) 外部の監視処理からアクセスがあったときに状態を通知する下記のような処理を監視対象サーバに作成し、WEB公開ディレクトリに設置する。
<?php

// 状態初期化
$web_status  = "OK";
$db_status   = "OK";
$mail_status = "OK";

// DB稼動チェック
$DAO = new Dao("oracle");
$DAO->err_log = "/var/log_db/status_chk_err.log";
$DAO->log_write = TRUE;
$DAO->connect(DB_NAME,DB_USER,DB_PASS);
$res = $DAO->s_query("select 'OK' STATUS from dual");
if ($res["tbl"][0]["STATUS"]!="OK"){ $db_status  = "NG";}
$DAO->close();
$DAO = NULL;

// SMTPサーバ稼動チェック
$cmd = 'ps -A | grep sendmail | wc -l | awk \'{print $1;}\'';
$cnt = exec($cmd);
if ($cnt==0){
	$mail_status = "NG";
}

// 状態表示
echo "{$web_status} {$db_status} {$mail_status}";
?>

[処理内容の補足]

 ・ここではPHPにしたが稼動しているべきアプリの言語で
  書くのがよいと思う。

 ・SSLやBASIC認証と組み合わせて
  一般ユーザからのアクセスを拒否したほうがよい。

 ・DBにアクセスするアプリならDB接続を
  メール送信するアプリならメールサーバの稼動確認を行う。

 ・PHPのセーフモードがOnの場合はexecはダメだった気がする。

 ※DB周りは自前のクラスライブラリを利用。

  (2) 以下のようなスクリプトを対象サーバのネットワーク外にあるマシンに作成する
#!/bin/bash
#
# chkconfig: 345 99 01
# description: Process Check
# processname: chk_app
#

### 設定 START ##############################

# ステータス一時保存ファイル
status_txt="/tmp/svr_status.txt"

# このシェルの名前
own_name=`basename ${0}`

# 監視先サーバ名
server_name="www.example-server.com"

# 状態取得用URL
chk_url="http://${server_name}/xxxxxxx/xxxxx.php"

# チェック間隔(秒)
chk_range=600

# エラー時報告先ユーザ
email_to_file="/xxxx/xxxx/ADMIN_MAIL"

# 送信者
email_from="svr-chk@example.com"

# メール件名
subject="サーバ(${server_name})外部監視"

# メール送信用プログラム
sendmail="/usr/sbin/sendmail"
### 設定 END ################################


### 関数定義 START ##########################

## HELP表示
disp_help(){
        echo "
 使用法: `basename ${0}` start|stop

 プロセス監視を開始/終了する

 ※サーバの状態を外部監視します
"
}

## 報告メール送信
report_mail(){

email_to=`cat $email_to_file`

mail_body=`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_body
.
_EOMAIL_
}


## 重複起動の回避処理
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_app_main(){

CR='
'
	## 状態の初期化
	touch $status_txt
	pre_status=`cat $status_txt`
	if [ "$pre_status" == "" ];then
		pre_status="INIT INIT INIT"
	fi
	pre_web_server=`echo "$pre_status" | awk '{print $1;}'`
	pre_db_server=`echo "$pre_status" | awk '{print $2;}'`
	pre_ml_server=`echo "$pre_status" | awk '{print $3;}'`

	while [ ture ]
	do

		wget -O $status_txt $chk_url >/dev/null 2>&1

		status=`cat $status_txt`

		if [ "$pre_status" != "$status" ]; then

			msg1=""
			msg2=""
			msg3=""

			ml_status="停止"
			db_status="停止"
			web_status="停止"

			web_server=`echo "$status" | awk '{print $1;}'`
			db_server=`echo "$status" | awk '{print $2;}'`
			ml_server=`echo "$status" | awk '{print $3;}'`

			if [ "$web_server" != "$pre_web_server" ]; then
				if [ "$web_server" == "OK" ]; then
					web_status="起動"
				fi
				msg1="WEBサーバが${web_status}しました${CR}"
			fi

			if [ "$web_server" == "OK" ]; then

				if [ "$db_server" != "$pre_db_server" ]; then
					if [ "$db_server" == "OK" ]; then
						db_status="起動"
					fi
					msg2="DB(Oracle)サーバが${db_status}しました${CR}"
				fi

				if [ $ml_server != "$pre_ml_server" ]; then
					if [ "$ml_server" == "OK" ]; then
						ml_status="起動"
					fi
					msg3="メール(SMTP)サーバが${ml_status}しました${CR}"
				fi
			fi

			msg="${msg1}${msg2}${msg3}"

			report_mail "$msg"
		fi

		#
		pre_status="$status"
		pre_web_server="$web_server"
		pre_db_server="$db_server"
		pre_ml_server="$ml_server"

		# n秒待機
		sleep $chk_range
	done
}
### 関数定義 END ############################


### メイン処理 START ########################


# 引数取得
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


# STOP時は終了
if [ "$mode" == "stop" ];then
	exit 0
fi

# チェック処理
chk_app_main &
  (3) 上記のシェルを /etc/init.d 以下に配置し、サービスとして初期起動するようにしておく。
# cp chk_app /etc/init.d/
# chkconfig --add chk_app
# chkconfig --level 345 chk_app on

[補足]
 ・チェック処理自体が止まってしまった時の為に、
  cronで定期的に実行するなどの工夫が必要かも。。


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