イベントハンドラ


序文

イベントハンドラはホスト又はサービスの状態が変化すると実行されるオプションコマンドです。イベントハンドラのわかりやすい使用法(特にサービスの場合)は、誰かが気付く前に問題を修正することです。別の使用法としては、サービスやホストのイベントを外部データベースに記録することも考えられます。

イベントハンドラのタイプ

イベントハンドラには主に2つのタイプが - サービスイベントハンドラとホストイベントハンドラが定義されています。 イベントハンドラコマンドは(オプションで)、各ホストとサービスの定義内に定義されます。というのもこれらのイベントハンドラは特定のサービスやホストとのみ関わりを持つからで、ここでは「ローカルイベントハンドラ」と呼びます。サービスやホストにローカルイベントハンドラが定義されていると、ホストやサービスの状態が変化した時に実行されます。Event handler commands are (optionally) defined in each host and service definition.

また、メイン設定ファイルで グローバルホストイベントハンドラグローバルサービスイベントハンドラ オプションを設定することで個々のホストやサービスの状態の変化によって 実行されるグローバルイベントハンドラを設定することも出来ます。 グローバルイベントハンドラはローカルイベントハンドラ(サービス又はホスト)に 優先してすぐに実行されます。

いつイベントハンドラコマンドが実行されるのか?

サービスとホストイベントハンドラのコマンドはサービス又はホストが:

「ソフト」「ハード」状態とは? ここに説明があります。

イベントハンドラが実行される順番

グローバルイベントハンドラは特定のホストやサービスに設定したローカルイベントハンドラより先に実行される。

イベントハンドラコマンドを書く

大抵の場合、イベントハンドラコマンドはシェルかPerlスクリプトです。最低でもスクリプトは次のマクロを引数として持たなければならない。

サービスイベントハンドラマクロ: $SERVICESTATE$, $STATETYPE$, $SERVICEATTEMPT$
ホストイベントハンドラマクロ: $HOSTSTATE$, $STATETYPE$, $HOSTATTEMPT$

スクリプトは入ってくる引数を検査し、それらの値に基づき必要な動作をとります。イベントハンドラがどのように動作するのかを理解するのに最も良い方法は例を見ることです。ラッキーなことに例が一つここにあります。Nagiosディストリビューションの中のeventhandlers/サブディレクトリにもいくつかの例があります。いくつかの例は監視の冗長化を実装する外部コマンドの実例になっています。

イベントハンドラの権限

どのイベントハンドラもNagiosの実行ユーザと同じ権限で実行されます。つまり、システムのサービスを再起動させようとするスクリプト(一般的にこの種のタスクを実行するのにはroot権限が必要になるのですが)で問題が発生します。

理想を言えば、実装しようとしているイベントハンドラの種類を見定め、それに見合った権限をNagiosユーザに与え必要なシステムコマンドを実行させると良いでしょう。sudoを使おうとするかもしれませんが、これを実装するのはあなたの役割です。ドキュメントを読みそれが必要かどうか決めてください。

イベントハンドラコマンドのデバッグ

イベントハンドラコマンドをデバッグする際には、サービスチェックリトライロギングオプション,ホストチェックリトライロギングオプション, とイベントハンドラロギングオプションを有効にすることを強く勧めます。これら全てのロギングオプションはメイン設定ファイルで設定します。これらのロギングオプションを有効にすることでいつ、どういった理由でイベントハンドラが実行されたのか正確に知ることが出来ます。

イベントハンドラのデバッグを終えると、おそらくサービスチェックリトライロギングオプションとホストチェックリトライロギングオプションを無効にしたいと思うかもしれません。これらを有効にするとログファイルが早く一杯になりますが、ログローテーションを有効にしておくと気にしなくても良くなります。

サービスイベントハンドラの例

以下の例ではローカルマシン上のHTTPサーバーを監視しているとし、また、HTTPサービスのイベントハンドラコマンドとしてrestart-httpdを設定している。また、<max_check_attempts>オプションを4かそれ以上に設定している(つまり、実際に問題があるとみなされるまでに4回このサービスをチェックする)。サービスの定義(今話している部分のみ)はこんな感じになる....

define service{
	host_name			somehost
	service_description		HTTP
	max_check_attempts		4
	event_handler			restart-httpd
	...other service variables...
	}

イベントハンドラと一緒にサービスを定義したら、次にコマンドとしてイベントハンドラを定義しなければならない。コマンドラインに含まれ、イベントハンドラへ渡しているマクロに注意。- このことはは非常に重要だ!

define command{
	command_name	restart-httpd
	command_line	/usr/local/nagios/libexec/eventhandlers/restart-httpd  $SERVICESTATE$ $SERVICESTATETYPE$ $SERVICEATTEMPT$
	}

さあ、実際にイベントハンドラスクリプトを書こう(/usr/local/nagios/libexec/eventhandlers/restart-httpd ファイル)。

#!/bin/sh
#
# ローカルホスト上のウェブサーバをリスタートするイベントハンドラ
#
# 注意: このスクリプトはサービスチェックに3回失敗した場合(ソフトステート)か
#       ウェブサービスが何らかの理由で"ハードステート"になった場合にのみ
#       ウェブサーバの再起動を行います。
#


# HTTPサービスの状態を取得
case "$1" in
OK)
	# サービスは正常稼動中。何もしない・・・
	;;
WARNING)
    # サービスはおそらく稼動はしているはず。気にしない・・・
	;;
UNKNOWN)
	# なぜ未知の状態になっているか分からないので、何もしない・・・
	;;
CRITICAL)
	# あ!HTTPサービスに問題が起きた ...
	# でも"ソフト"?"ハード"?
	case "$2" in
		
	# "ソフト"状態とは、"ハード"状態に変化し、通知者に通知が届くよりも前の、
	# Nagiosがチェックを再試行している最中の状態を意味します。
	SOFT)
			
        # 何度チェックをした?初回のWebサーバチェックなどでは再起動したくない。
        # たまたまチェックに失敗しただけかもしれないから
		case "$3" in
			
		# Webサーバを再起動する前に3回チェックが完了するまで待とう。	
		# もし4度目のチェック(Webサーバの再起動の後) に失敗したら、
		# ステートタイプを"ハード"にして、通知者へ問題を通知する。
		# うまくいけば、このサーバ再起動が成功し、4度目のチェック結果は"ソフト"結果
		# をもってリカバリするかもしれない。もしそうなれば、この問題は我々が修正したので
		# 誰も通知を受け取らないで済む。
		3)
			echo -n "Restarting HTTP service (3rd soft critical state)..."
			# HTTPDサーバの起動スクリプトを発行する。
			/etc/rc.d/init.d/httpd restart
			;;
			esac
		;;
				
	# HTTPサービスが修正されず、"ハードエラー"に変わった。
	# 以下のコードで再起動した方がよいが、理由は不明。
	# 最後に一度だけ試してみたほうがいいでしょう?
	# 注意: 通知者はこの時点で既にこのサービスに関する問題通知を受け取っている筈である。
	# (このサービスの通知を無効にしていなければ)
	HARD)
		echo -n "Restarting HTTP service..."
		# HTTPDサーバの起動スクリプトから再起動する。
		/etc/rc.d/init.d/httpd restart
		;;
	esac
	;;
esac
exit 0

上の例では、異なる二つの場合 - HTTPサービスの再試行が3度目("ソフト"エラー状態)になった後とサービスが"ハード"状態になった後 - にローカルマシン上のウェブサーバを再起動しようとします。"ハード"状態は実際に起こらないようになっています。なぜならスクリプトによってまだ"ソフト"状態にある(つまり3回目の再試行)サービスが短縮され再起動されるからです。

注意する点は、サービスイベントハンドラは最初にサービスが"ハード"状態になった時のみ実行されるということです。 このことにより"ハード"状態になる度にウェブサーバを再起動し続けることを避けることが出来ます。