syslog-ngでログを監視して、特定の文字列を検知したらメールする

以下のバージョンで行います。

$ rpm -qa | grep syslog-ng
syslog-ng-3.0.2-1.rhel5

特定の文字列を検知する方法

メッセージのみ見れば良いので fileterで message() を利用します。


参考=>8.4. Filter functions

match() match(regexp) Match a regular expression to the headers and the message itself (i.e., the values returned by the MSGHDR and MSG macros). Note that in syslog-ng version 2.1 and earlier, the match() filter was applied only to the text of the message, excluding the headers. This functionality has been moved to the message() filter. To limit the scope of the match to a specific part of the message (identified with a macro), use the match(regexp value("MACRO")) syntax.

matchはヘッダーとメッセージ両方を正規表現で見ます。ただし、 version 2.1より前はメッセージのみ見ていたことに注意してください。メッセージだけを見る機能は message() に動かされました。matchの部分をメッセージに特定する場合には、match(regexp value("MACRO")) 構文を利用してください。

message() message(regexp) Match a regular expression to the text of the log message, excluding the headers (i.e., the value returned by the MSG macros). Note that in syslog-ng version 2.1 and earlier, this functionality was performed by the match() filter.

ログメッセージのテキストに正規表現をマッチさせます。ヘッダーは除きます。syslog-ng2.1より前のバージョンではこの機能はmatch() フィルタによって実行されていたことに注意してください。


と書いてあると思います。メッセージだけを見ればいいので、message() で実装してみましょう。


例えば、以下のように実装します。

source s_local { file ("/proc/kmsg" program_override("kernel: ")); unix-stream("/dev/log"); internal(); };
destination d_test { file("/var/log/filter_message_test.log");};
filter f_test   { facility(local6) and level(info) and message(TEST); };
log { source(s_local); filter(f_test);  destination(d_test); };

リスタートして反映させます。

$ sudo /etc/init.d/syslog-ng restart
Restarting syslog-ng: Stopping syslog-ng: OK
Starting syslog-ng: OK

logger を利用して、フィルターされるかどうか確認します。

$ logger -p local6.info TEST Message

ちゃんとロギングされていました。

$ sudo cat /var/log/filter_message_test.log
Jun 16 16:23:34 Dev_adc admin: TEST Message

logger を利用して、「フィルターするべきでない」メッセージを流してみます。

$ logger -p local6.info hogehoge

フィルターするべきでないメッセージはロギングされていません。成功です!

$ sudo grep hoge /var/log/filter_message_test.log
$

メールの送信

今度は、特定のメッセージがフィルターに引っかかった場合に、そのメッセージを program を利用してメールに転送するようにしましょう。
メールへの転送は mail プログラムを利用します。

例えば、以下のように実装します。

source s_local { file ("/proc/kmsg" program_override("kernel: ")); unix-stream("/dev/log"); internal(); };
destination d_notify { program("/usr/local/bin/syslog-ng-notify"); };
filter f_test   { facility(local6) and level(info) and message(TEST); };
log { source(s_local); filter(f_test);  destination(d_test); };


/usr/local/bin/syslog-ng-notify の内容は例えば以下のようになっています。 メッセージを mail コマンドにパイプして渡して、hoge@fuga-mail.com に送信しています。

#!/bin/sh
TO=hoge@fuga-mail.com
while read line
do
    echo $line | /bin/mail -s "mail_title `hostname`" $TO
done


これで、logger で フィルターに引っかかるメッセージを送ってみましょう。

$ logger -p local6.info TEST Message

送信できればOKです!/var/log/maillog などで送信結果を確認してください。


これで完了です!

参考
http://www.k4.dion.ne.jp/~mms/unix/linux_com/mail.html
Identity & Access Management for the Real World | One Identity



メール送信の部分でもっといいやり方がありそうな気がします・・・こうやったほうがいいよ!などありましたら突っ込みお願いします><