* [[サービス監視]] - 内部監視 [#ic7255cd]

  内部監視用の処理は必要なプロセスが稼動しているかどうかの確認しか行わないので対象サーバにて定期的に実行する。~
 
#html(<table><tr><td colspan="2" style="font-size:100%;">(1) 以下のようなシェル(ファイル名:chk_proc)を作成する。</td></tr><tr><td style="font-size:100%;">)
#html(<table><tr><td colspan="2" style="font-size:100%;">  (1) 以下のようなシェル(ファイル名:chk_proc)を作成する。</td></tr><tr><td style="font-size:100%;">)
 #!/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  ########################
#html(</td><td valign="top" style="font-size:100%;">)
[処理内容の補足]~

 ・チェックを行う各プロセスの起動スクリプトを&br;
  プロセス名と同じ名前で作成しておく事により、~
  停止時に再起動を試みるようにしている。)~

 ・この処理自体がチェック対象のプロセスよりも&br;
  先に起動しないようにする。~
  (一応、最初のチェック時は5秒間待ってから&br;
   チェックするようにはなっているが。。)~
#html(</td></tr></table>)

#html(<table><tr><td colspan="2" style="font-size:100%;">(2) 上記のシェルを /etc/init.d 以下に配置し、サービスとして初期起動するようにしておく。</td></tr><tr><td style="font-size:100%;">)
#html(<table><tr><td colspan="2" style="font-size:100%;">  (2) 上記のシェルを /etc/init.d 以下に配置し、サービスとして初期起動するようにしておく。</td></tr><tr><td style="font-size:100%;">)
 # cp chk_proc /etc/init.d/
 # chkconfig --add chk_prc
 # chkconfig --level 345 chk_prc on
#html(</td><td valign="top" style="font-size:100%;">)
[補足]~
 ・チェック処理自体が止まってしまった時の為に、&br;
  cronで定期的に実行するなどの工夫が必要かも。。~
#html(</td></tr></table>)

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS