InsertSyslogSQL

id:dacci:20070112:1168738444 の続き。

syslog-ng.conf

必要な情報をタブ区切りにして出力するようなテンプレートを指定する。

template t_mysql {
    template("$SOURCEIP\t$FACILITY\t$PRIORITY\t$LEVEL\t$TAG\t$YEAR-$MONTH-$DAY $HOUR:$MIN:$SEC\t$PROGRAM\t$MSG\n");
    template-escape(no);
};

destination d_mysql { pipe("/var/log/mysql.pipe" template(t_mysql)); };

log { source(s_udp); destination(d_mysql); };

/root/bin/syslog2mysql.pl

タブで区切って、\ や " などをエスケープして SQL サーバーに流す。DBI と DBD::mysql がいるので、適宜 CPAN。

#!/usr/bin/perl -w --

## Libraries
use strict;
use DBI;
use IO::File;

## Configurations
my $DB_HOST = "localhost";
my $DB_NAME = "syslog";
my $DB_USER = "syslogfeeder";
my $DB_PASSWD = "PW_HERE";
my $PIPE_NAME = "/var/log/mysql.pipe";

my $db = DBI->connect("DBI:mysql:$DB_NAME:$DB_HOST", $DB_USER, $DB_PASSWD) || die $!;
my $file = IO::File->new($PIPE_NAME, "r") || die $!;

while (my $line = $file->getline()) {
    chomp($line);
    $line =~ s/([\\"'])/\\$1/g;

    my ($host, $facility, $priority, $level, $tag, $datetime, $program, $msg) = split(/\t/, $line);
    my $sth = $db->prepare("INSERT INTO logs (host, facility, priority, level, tag, datetime, program, msg) VALUES (\"$host\", \"$facility\", \"$priority\", \"$level\", \"$tag\", \"$datetime\", \"$program\", \"$msg\");");
    $sth->execute();
    $sth->finish();
}

$file->close();
$db->disconnect();

/etc/init.d/syslog-ng

名前付きパイプの作成と、前述のスクリプトの実行。
syslog-ng が終了するときにパイプをクローズするのかな?その時に一緒にスクリプトも終了するので、stop() は特にいじってない。パイプになにも書き込まれなかった時かなんかにはスクリプトのプロセスが残るので、本当はちゃんとやったほうがいいんだろうな。。。

[ ! -e /var/log/mysql.pipe ] && mkfifo /var/log/mysql.pipe

start() {
・・・
    [ $retval -eq 0 ] && touch $lockfile && /root/bin/syslog2mysql.pl &
・・・
}

reload() {
・・・
    /root/bin/syslog2mysql.pl &
・・・
}