Logwatch とは
- Logwatch
- 日次でシステム内のさまざまなログから見つかった問題を通知する
/etc/cron.daily/0logwatch
で実行される
- デフォだと root へのメールで通知される
- デフォでいろいろなログの通知が組み込まれている
ls /usr/share/logwatch/scripts/services/
独自の通知の追加
例えば oreore というサービスのログを追加することにします。
ログファイルの設定
oreore のログファイルに関する設定を追加します。
/etc/logwatch/conf/logfiles/oreore.conf
LogFile = oreore.log LogFile = oreore.log-*[0-9] Archive = oreore.log-*.gz
LogFile にはログファイル名を glob 形式で指定します。パスは /var/log/
からの相対です。このディレクトリ以外のログを指定したい場合は絶対パスで指定します。
Archive には gzip でアーカイブされたログファイルを指定します。ただ、この設定は普段は使われません(logwatch の実行時のオプションでアーカイブされたログも走査するかのオプションがあるけどデフォで指定されていない)。
また、通常はこの設定ファイルでログファイルを日付でフィルタするための設定を記述します。例えば syslog 形式のログであれば次のように記述すれば日付でフィルタされます。
*ApplyStdDate
この記述によって /usr/share/logwatch/scripts/shared/applystddate
にログファイルがパイプされるようになります。
他にも /usr/share/logwatch/scripts/shared/
ディレクトリにあるスクリプトを指定することができます。ログファイルに独自の処理を行いたい場合は下記のディレクトリにスクリプトを配置します。
/etc/logwatch/scripts/logfiles/oreore/
このディレクトリに配置したスクリプトは oreore のログの走査時に自動的に適用されます。
例えば次のような内容で作成します。
/etc/logwatch/scripts/logfiles/oreore/applydate
use Logwatch ':dates'; my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0; my $SearchDate = TimeFilter('\[%Y-%m-%dT%H:%M:%S\]'); if ( $Debug > 5 ) { print STDERR "DEBUG: Inside oreore..\n"; print STDERR "DEBUG: Looking For: (" . $SearchDate . ")\n"; } while (defined($ThisLine = <STDIN>)) { if ($ThisLine =~ s/^$SearchDate\s+//o) { print $ThisLine; } }
既存のスクリプトからほとんどコピペです。Logwatch
モジュールの TimeFilter
を使えば日時でフィルタするための正規表現を簡単に作ることができます。例えば↑の例だと $SearchDate
は \[2016-04-14T..:..:..\]
のようになります。
この例では perl でスクリプトを作成していますが、シェバングを書けばそのインタプリタで実行されるので、好きな言語で作成することができます。
サービスの設定
oreore のサービスに関する設定を追加します。
/etc/logwatch/conf/services/oreore.conf
Title = "oreore report" LogFile = oreore
Title は通知のレポートで使われるサービスの名称です。
LogFile には↑で設定したログファイルの設定名を指定します。この例ではログファイルとサービスで同じ oreore
という設定名ですが、例えばこのサービスが /var/log/messages
にログを出すようになっているのなら LogFile = messages
と指定したりすることもあります。
また、ログファイルの設定と同じように、フィルタを下記のように記述することができます。
*Remove = "^(DEBUG|INFO):"
指定できるものはログファイルの設定と同じです(/usr/share/logwatch/scripts/shared/
のスクリプト)。
最後に、レポートを出力するためのスクリプトを /etc/logwatch/scripts/services/oreore
に作成します。ログファイルの設定やサービスの設定によってフィルタされたログが標準入力から入ってくるので、それっぽい出力にしてやれば OK です。
例えば、単にそのまま流すだけですが、次のような内容です。
/etc/logwatch/scripts/services/oreore
while (defined($ThisLine = <STDIN>)) { print $ThisLine; }
もちろん perl 以外でも作成できるので、そのまま流すだけなら下記で十分です。
#!/bin/bash
cat
環境変数
ログファイルやサービスの設定ファイルで次のように変数を記述すると、
$oreore_value = 123
スクリプトで環境変数として取り出せます。
my $oreore_value = $ENV{'oreore_value'} || 0;
変数名に大文字を用いてもすべて小文字に置換されます。
ログファイルの設定ファイルで記述した変数は、ログファイルとサービスの両方のスクリプトで有効になります。ただ、見た感じ既存のログファイルの設定ファイルで変数が記述されているものはありませんでした。
サービスの設定ファイルで記述した変数は、サービスのスクリプトのみで有効になります。
動作確認
次のように環境変数を設定しつつログファイルからスクリプトをパイプしていくと最終的な出力が得られます。
export LANG=C PERL5LIB=/usr/share/logwatch/lib/ LOGWATCH_DEBUG=9 LOGWATCH_DATE_RANGE=today sudo cat /var/log/oreore.log | perl /etc/logwatch/scripts/logfiles/oreore/applydate | perl /usr/share/logwatch/scripts/shared/remove "^(DEBUG|INFO):" | perl /etc/logwatch/scripts/services/oreore
切り貼りすれば途中までの結果を出力したりもできるのでデバッグが捗ります。
最終的な動作確認には 次のように logwatch を実行します(CentOS 7)。
sudo logwatch --service oreore --output stdout --range today
CentOS 6 だと --output
オプションが無くて、代わりに --print
を使います。
sudo logwatch --service oreore --print--range today
フィルタ
ログファイルやサービスの設定で指定可能なフィルタ(/usr/share/logwatch/scripts/shared/
のスクリプト)には以下のようなものがあります。
- applybinddate
- applyeurodate
- applyhttpdate
- applystddate
- applytaidate
- applyusdate
- applyvsftpddate
- 日付でフィルタ(ログファイルの形式により様々)
- eventlogonlyservice
- eventlogremoveservice
- 謎・・MSWinEventLog とかいう記述が見えるけど
- expandrepeats
last message repeated 10 times
のように省略されたログを展開
- hosthash
- 謎・・syslog 形式のログからホスト名の一覧を出力するっぽいけど
- hostlist
- 謎・・syslog 形式のログからホスト名の一覧をテンポラリに書き出すっぽいけど
- multiservice
- syslog 形式のログで特定のサービスの以外の行を除去
*RemoveService = ntpd,ntpdate
のように引数をカンマ区切りで指定する
- onlycontains
- 指定されたパターンにマッチする行のみを抽出
*OnlyContains = ^(ERROR|WARN):
のように正規表現で指定する
- onlyhost
- syslog 形式のログで特定のホストの行のみを抽出
- ホスト名は
logwatch.conf
のHostLimit
または引数で指定する logwatch.conf
で指定するときはカンマ区切りまたは正規表現で指定する- カンマの有無で意味が変わる
- 引数で指定するときは正規表現で指定する
- onlyservice
- syslog 形式のログで特定のサービスの行のみを抽出
*OnlyService = (spamd|sendmail)
のように引数を正規表現で指定する
- remove
- 指定されたパターンにマッチする行を除去する
*remove = ^(DEBUG|INFO):
のように正規表現で指定する
- removeheaders
- syslog 形式のログのメッセージ以外の部分を削除
Apr 13 23:20:01 localhost systemd: hogehoge
->hogehoge
- removeservice
- syslog 形式のログで特定のサービスの行を除去
*RemoveService = anacron,cron
のように引数をカンマ区切りで指定する
詳しいことは less /usr/share/doc/logwatch-*/HOWTO-Customize-LogWatch
で。
参考
全部自分の記事だけど・・