Nagiosのpassive checkとrsyslogを組み合わせてみた(2)
前回で、Nagios に対して、アラート通知を行う方法を書いたので、今回は、rsyslog の内容をNagios のアラート形式に書き換える方法について書いていく。
Nagios の理解できる形式は、次のようなものになる。
echo "[$(date +%s)] PROCESS_SERVICE_CHECK_RESULT;localhost;Current Load;1;testtest"
このうち、Current Load の部分にはNagios で service として指定されているものが入り、上の例ではNagios コンソール上で、Current Load が変更される。
筆者の環境では、 ログの確認を一律に行うため、他のサービスとは分割し、次のようなログを確認するためのサービスを加えた。
define service { hostgroup_name logcheck-servers service_description check_log active_checks_enabled 0 check_command check_ping!100.0,20%!500.0,60% use generic-service notification_interval 0 ; set > 0 if you want to be renotified } define hostgroup { hostgroup_name logcheck-servers alias logcheck servers members localhost }
service の中でcheck_ping で監視を行っているように見えるが、実際には、active_checks_enabled 0 の設定によってpingチェックは行わないようになっており、実質ではpassive check 専用となっている。デフォルトの設定からコピペした部分があるので、最小の設定にはなっていないかもしれない ,,,
check_log に対して、ログを書き込むものとすると、 rsyslog を編集する PythonスクリプトはNagios のパイプに次のような文字列を書き込むことになる。
[$(date +%s)] PROCESS_SERVICE_CHECK_RESULT;localhost;check_log;1;testtest
testtestはエラーメッセージの本体で、syslogのメッセージから転載する。 その前の1は、Nagiosの状態を表し、 1はWARN, 2 はCRITICAL を指すが、syslog からの変換では、crit 以上をCRITICAL, warn 以上をWARNあたりに割り振ればよいのではなかろうか。。
問題はsyslog形式の時刻を Epoch へ変換する方法だが、Pythonのドキュメントを確認したところ、timeモジュールの strptime (フォーマット文字列をtimeを表すタプルへと変換する )を使うとそのまま解析できそうなことが分かった。ただ、筆者はrsyslog 側で少し工夫させることにした。(テキスト形式を経由すると、parsing のところでコストがかかるかと思ったため。もっとも以下のやりかたでもあまり状況は変わらないのだが。。。)
rsyslog ではテンプレートの機能を使い、syslogの出力フォーマットを変更できるが、ログの発生時刻については、オプションを設定することで、いくつかの形式で出力することができる。ここでは、 timereported:::date-mysql のフォーマットを使った。
$template preciseaaa,"%syslogpriority%,%syslogfacility%,%timereported:::date-mysql%,%HOSTNAME%,%syslogtag%,%msg%\n" *.*;auth,authpriv.none /tmp/aaa;preciseaaa
サンプルのpreciseからコピペしたため、いらないものも混じっているが、大体出力は次のようになる。
6,5,20091002001346,localhost,rsyslogd:, [origin software="rsyslogd" swVersion="1.19.12" x-pid="6257"] [x-configInfo udpReception="Yes" udpPort="514" tcpReception="Yes" tcpPort="514"] restart
dateの出力が 2009/10/02 00:13:46 だと上のように"20091002001346"という出力になるため、Pythonでの解析がやりやすくなる。実際、timestamp として上の形式(YYYYMMDDhhmmss)を取り込んだ後、
year=int(timestamp[0:4]) month=int(timestamp[4:6]) day=int(timestamp[6:8]) hour=int(timestamp[8:10]) minute=int(timestamp[10:12]) second=int(timestamp[12:14]) t=time.mktime( (year,month,day,hour,minute,second,0,0,0) )
のようにすることで、Epochからの秒数 t を得ることができた。ちなみに、 time.mktime は、 秒数を表すタプルを受け取って、 Epochからの秒数とする関数である。
ここまでで、rsyslog の出力をNagios 形式に変換する方法がわかったので、次回は、rsyslog の出力をPythonに渡す方法について書いていく。これがわかれば、後は機械的にsyslogの出力をNagiosに渡すだけである。