たいていのsyslogのデフォルトの設定だと、
- 同じログが結構な量、複数のファイルに記録されて(IO負荷的、ディスクサイズ的に)無駄だなぁ
- 日付のフォーマットが機械処理しづらいなぁ
- ローテートがめんどいなぁ
と思ってたので、今つくってる環境では慣習を気にせずに syslog-ng (v2.0.9) の設定をしてみたのでそのメモです。
不要なログは記録しない
options {
...
mark_freq(0);
stats_freq(0);
...
}
日付の形式を変える
options {
...
ts_format(iso);
...
}これで、こんなの
Dec 19 16:44:20 HOST ...
から、こんなの
2008-12-19T14:07:52+09:00 HOST ...
に変わります。
facilityごとにわける
facilityごとのfilterを作る。
desticationは$FACILITYというfacility名に展開されるマクロを使って記述を簡素化。
ただ、authとauthprivはひとつにまとめたいので、例外的に設定してます。
destination df_facility { file("/var/log/archive/${FACILITY}/$YEAR-$MONTH"); };
destination df_auth { file("/var/log/archive/auth/$YEAR-$MONTH"); };
filter f_kern { facility(kern); };
...
filter f_auth { facility(auth, authpriv); };
...
filter f_local7 { facility(local7); };
log { source(s_local) ; filter(f_kern); destination(df_facility); };
...
log { source(s_local) ; filter(f_auth); destination(df_auth); };
...
levelごとにわける (一部)
debian/syslog-ng.conf からそのまま。
filter f_emerg { level(emerg); };
filter f_debug { level(debug) and not facility(auth,authpriv,news,mail); };
filter f_at_least_crit { level(crit..emerg); };
filter f_at_least_err { level(err..emerg); };
filter f_at_least_warning { level(warning..emerg); };
filter f_at_least_notice { level(notice..emerg); };
filter f_at_least_info { level(info..emerg); };
ログローテート要らず
こんな感じで、さいしょっからログの出力先を、ログ種別と月次でわける。
destination df_facility { file("/var/log/archive/${FACILITY}/$YEAR-$MONTH"); }んで、月初とか(毎日00:01とかでもOK)にこんなスクリプトを実行してsymlinkする。
#!/bin/sh # Time-stamp: <2008-12-19 16:03:22 JST, hirose31> # /var/log/TYPE (symlink) # /var/log/archive/TYPE/YYYY-MM timestamp=$(date '+%Y-%m') facility="kern user mail daemon auth syslog lpr news uucp cron ftp local0 local1 local2 local3 local4 local5 local6 local7" level="emerg alert crit err warning notice info debug" custom="" for d in $facility $level $custom; do [ -d "/var/log/archive/${d}" ] || continue ln -sf archive/${d}/${timestamp} /var/log/${d} done
今のログを見たいときは /var/log/auth を見る。
過去のを見たいときは /var/log/archive/auth/2008-01 とかを見る。
マクロを使った効率的なログの集約
WEB+DB PRESS Vol.40 にも書いたんですが、複数ある Apache のログを syslog で飛ばしてログサーバに集約する例。
ログはloggerを使ってsyslogに流す。
facility.levelは固定(local6.info)で、
tagにサービス (VirtualHost) の識別子を入れる。
<VirtualHost *> ServerName d.hatena.ne.jp ... CustomLog "|/usr/bin/logger -t diary -p local6.info --" orenolog ... </VirtualHost> <VirtualHost *> ServerName b.hatena.ne.jp ... CustomLog "|/usr/bin/logger -t bookmark -p local6.info --" orenolog ... </VirtualHost>
Apacheが動いているマシンのsyslong-ng.confはこんな感じで、全部ログサーバ(log.example.org)に転送する。
filter f_httpd {
facility(local6) and level(info);
};
destination df_httpd {
udp("log.example.org");
};
log { source(s_local); filter(f_httpd); destination(df_httpd); };ログサーバのsyslog-ng.confはこんな感じで、loggerのtagで指定した識別子を使って複数のApacheからのログをまとつつディレクトリをわけて整理する。
filter f_httpd {
facility(local6) and level(info);
};
destination df_httpd_aggregate {
file("/var/log/httpd/realtime/${PROGRAM}/acc_$YEAR-$MONTH-$DAY"
perm(0644)
dir_perm(0750)
);
};
log { source(s_remote); filter(f_httpd); destination(df_httpd_aggregate); };
通知
とあるログが出力されたら、メールやIRCやIMやトランスバイブレータなどを使って通知する方法。
ひとつめは、ログをファイルじゃなくて名前付きパイプに書く。
destination dp_notifier { pipe("/dev/notifier"); };あとはこの名前付きパイプをreadしてログを読んで、然るべき方法で通知を実行するプログラムを走らせておけばOK。
ふたつめは、プログラムに標準入力でログを渡す方法。
destination dx_notifier { program("/path/to/notifier"); };このプログラムはsyslog-ngから起動されて、ログが出力され次第、標準入力から読めます。なので、exitしないでstdinをreadしてればOK。exitしてもいいけど、そするとログが吐かれる度にプロセス起動となりDoSっぽくのでやめたほうがいいと思います。
filterとlogはこんな感じで。
filter f_auth_fail {
( program("sshd")
and (match("Invalid user") or match("Failed password for")) )
or
( program("login")
and (match("authentication failure") or match("FAILED LOGIN")) );
};
log {
source(s_local);
filter(f_auth_fail);
destination(dp_notifier);
destination(dx_notifier);
};
パフォーマンス
syncとかバッファリングとかudpとかtcpとか。このへんは追々。なんか情報あったら教えてください><
options {
chain_hostnames(0);
time_reopen(10);
time_reap(360);
sync(0);
mark_freq(0);
stats_freq(0);
log_fifo_size(2048);
log_msg_size(2048);
create_dirs(yes);
ts_format(iso);
owner(root);
group(root);
perm(0640);
dir_owner(root);
dir_group(root);
dir_perm(0755);
use_dns(yes);
};
### sources ##############################################################
source s_local {
internal();
unix-stream("/dev/log");
file("/proc/kmsg" log_prefix("kernel: "));
};
source s_remote {
udp();
tcp();
};
### destinations #########################################################
destination df_facility { file("/var/log/archive/${FACILITY}/$YEAR-$MONTH"); };
destination df_auth { file("/var/log/archive/auth/$YEAR-$MONTH"); };
destination df_level { file("/var/log/archive/${LEVEL}/$YEAR-$MONTH"); };
destination du_all { usertty("*"); };
destination dp_xconsole { pipe("/dev/xconsole"); };
#destination dn_logserver { udp("log.local"); };
destination dp_notifier { pipe("/dev/notifier"); };
#destination dx_notifier { program("/path/to/notifier"); };
### filters ##############################################################
filter f_kern { facility(kern); };
filter f_user { facility(user); };
filter f_mail { facility(mail); };
filter f_daemon { facility(daemon); };
filter f_auth { facility(auth, authpriv); };
filter f_syslog { facility(syslog); };
filter f_lpr { facility(lpr); };
filter f_news { facility(news); };
filter f_uucp { facility(uucp); };
filter f_cron { facility(cron); };
filter f_ftp { facility(ftp); };
filter f_local0 { facility(local0); };
filter f_local1 { facility(local1); };
filter f_local2 { facility(local2); };
filter f_local3 { facility(local3); };
filter f_local4 { facility(local4); };
filter f_local5 { facility(local5); };
filter f_local6 { facility(local6); };
filter f_local7 { facility(local7); };
# emerg alert crit err warning notice info debug
filter f_emerg { level(emerg); };
filter f_debug { level(debug) and not facility(auth,authpriv,news,mail); };
filter f_at_least_crit { level(crit..emerg); };
filter f_at_least_err { level(err..emerg); };
filter f_at_least_warning { level(warning..emerg); };
filter f_at_least_notice { level(notice..emerg); };
filter f_at_least_info { level(info..emerg); };
filter f_xconsole {
filter(f_at_least_warning);
};
filter f_auth_fail {
( program("sshd")
and (match("Invalid user") or match("Failed password for")) )
or
( program("login")
and (match(" authentication failure") or match("FAILED LOGIN")) );
};
### logs #################################################################
log { source(s_local) ; filter(f_kern); destination(df_facility); };
log { source(s_local) ; filter(f_user); destination(df_facility); };
log { source(s_local) ; filter(f_mail); destination(df_facility); };
log { source(s_local) ; filter(f_daemon); destination(df_facility); };
log { source(s_local) ; filter(f_auth); destination(df_auth); };
log { source(s_local) ; filter(f_syslog); destination(df_facility); };
log { source(s_local) ; filter(f_lpr); destination(df_facility); };
log { source(s_local) ; filter(f_news); destination(df_facility); };
log { source(s_local) ; filter(f_uucp); destination(df_facility); };
log { source(s_local) ; filter(f_cron); destination(df_facility); };
log { source(s_local) ; filter(f_ftp); destination(df_facility); };
log { source(s_remote) ; filter(f_local1); destination(df_facility); };
log {
source(s_local);
filter(f_emerg);
destination(df_level);
destination(du_all);
destination(dp_notifier);
#destination(dx_notifier);
};
log {
source(s_local);
filter(f_debug);
destination(df_level);
};
log {
source(s_local);
filter(f_xconsole);
destination(dp_xconsole);
};
log {
source(s_local);
filter(f_auth_fail);
destination(dp_notifier);
#destination(dx_notifier);
};