イベントハンドラ


イントロダクション

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

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

二つの定義されている主なイベントハンドラ - サービスイベントハンドラとホストイベントハンドラがあります。イベントハンドラコマンドは(オプションで)、各ホストとサービスの定義内に定義されます。というのもこれらのイベントハンドラは特定のサービスやホストとのみ関わりを持つからで、ここでは「ローカルイベントハンドラ」と呼びます。サービスやホストにローカルイベントハンドラが定義されていると、ホストやサービスの状態が変化した時に実行されます。

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

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

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

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

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

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

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

大抵の場合、イベントハンドラコマンドはシェルか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$ $STATETYPE$ $SERVICEATTEMPT$
	}

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

#!/bin/sh
#
# Event handler script for restarting the web server on the local machine
#
# Note: This script will only restart the web server if the service is
#       retried 3 times (in a "soft" state) or if the web service somehow
#       manages to fall into a "hard" error state.
#


# What state is the HTTP service in?
case "$1" in
OK)
	# The service just came back up, so don't do anything...
	;;
WARNING)
	# We don't really care about warning states, since the service is probably still running...
	;;
UNKNOWN)
	# We don't know what might be causing an unknown error, so don't do anything...
	;;
CRITICAL)
	# Aha!  The HTTP service appears to have a problem - perhaps we should restart the server...

	# Is this a "soft" or a "hard" state?
	case "$2" in
		
	# We're in a "soft" state, meaning that Nagios is in the middle of retrying the
	# check before it turns into a "hard" state and contacts get notified...
	SOFT)
			
		# What check attempt are we on?  We don't want to restart the web server on the first
		# check, because it may just be a fluke!
		case "$3" in
				
		# Wait until the check has been tried 3 times before restarting the web server.
		# If the check fails on the 4th time (after we restart the web server), the state
		# type will turn to "hard" and contacts will be notified of the problem.
		# Hopefully this will restart the web server successfully, so the 4th check will
		# result in a "soft" recovery.  If that happens no one gets notified because we
		# fixed the problem!
		3)
			echo -n "Restarting HTTP service (3rd soft critical state)..."
			# Call the init script to restart the HTTPD server
			/etc/rc.d/init.d/httpd restart
			;;
			esac
		;;
				
	# The HTTP service somehow managed to turn into a hard error without getting fixed.
	# It should have been restarted by the code above, but for some reason it didn't.
	# Let's give it one last try, shall we?  
	# Note: Contacts have already been notified of a problem with the service at this
	# point (unless you disabled notifications for this service)
	HARD)
		echo -n "Restarting HTTP service..."
		# Call the init script to restart the HTTPD server
		/etc/rc.d/init.d/httpd restart
		;;
	esac
	;;
esac
exit 0

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

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