必要な場合、tcp経由で記録する設定を追加する。
mysqlのINSERT文をログフォーマットにする。1秒ごとに個別のファイルに残す。
フィルターでloggerコマンドのデフォルト値などの場合のみに記録するようにする。
src, kernsrc, net のログをフィルターを通した後にINSERT文のフォーマットで記録する。
$ rcsdiff -r1.15 /etc/config-archive/etc/syslog-ng/syslog-ng.conf,v /etc/syslog-ng/syslog-ng.conf =================================================================== RCS file: /etc/config-archive/etc/syslog-ng/syslog-ng.conf,v retrieving revision 1.15 diff -r1.15 /etc/syslog-ng/syslog-ng.conf 23c23 < source net { udp(); }; --- > source net { udp(); tcp(port(4800) keep-alive(yes) max_connections(256)); }; 60a61,64 > destination database { file("/var/log/dblog/fulllog.$YEAR.$MONTH.$DAY.$HOUR.$MIN.$SEC" > template("INSERT INTO logs$YEAR$MONTH (crtm, host, addr, facility, level, pri, program, pid, msghdr, msg) VALUES('$ISODATE', '$HOST', INET_ATON('$SOURCEIP'), '$FACILITY_NUM', '$LEVEL_NUM', '$PRI', '$PROGRAM', '$PID', '$MSGHDR', '$MSG');\n") > owner(root) group(root) perm(0600) dir_perm(0700) create_dirs(yes) template-escape(yes)); }; > 91a96,97 > filter f_database { facility(user) and level(notice) }; > 117a124,125 > > log { source(src); source(kernsrc); source(net); filter(f_database); destination(database); };
mysqlの設定。
データベース作成、専用書き込みユーザー作成、テーブルとトリガー(update,deleteを邪魔する)作成。
$ cat bin/syslog.sql -- CREATE DATABASE syslog; -- GRANT SELECT,INSERT ON syslog.* TO syslogappend@localhost IDENTIFIED BY 'syslogappendpasswd'; DROP TABLE IF EXISTS logs201107; CREATE TABLE logs201107 ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, crtm TIMESTAMP NOT NULL, host VARBINARY(63) NOT NULL, addr INT UNSIGNED NOT NULL, facility TINYINT NOT NULL, level TINYINT NOT NULL, pri INT NOT NULL, program VARBINARY(31) NOT NULL, pid SMALLINT UNSIGNED NOT NULL, msghdr VARBINARY(63) NOT NULL, msg BLOB NOT NULL, PRIMARY KEY (id) ) ENGINE=MyISAM DEFAULT CHARSET=binary; DROP TRIGGER IF EXISTS trigger_logs201107_before_update; DROP TRIGGER IF EXISTS trigger_logs201107_before_delete; DELIMITER | CREATE TRIGGER trigger_logs201107_before_update BEFORE UPDATE ON logs201107 FOR EACH ROW BEGIN CALL ERROR_UPDATE_NOT_ALLOWED(); END; | CREATE TRIGGER trigger_logs201107_before_delete BEFORE DELETE ON logs201107 FOR EACH ROW BEGIN CALL ERROR_DELETE_NOT_ALLOWED(); END; | DELIMITER ;
ログをDBに書きこむスクリプト。
$ cat bin/syslog.sh #!/bin/sh LANG=C LC_ALL=C PATH="/bin:/usr/bin" SLEEP=1 while true do FILE=$(find /var/log/dblog/ -name "fulllog*" | sort | head -n1) if [ -f "$FILE" ]; then echo $FILE"を処理します。" cat $FILE | mysql -usyslogappend -psyslogappendpasswd syslog if [ $? -ne 0 ]; then echo "失敗" exit 1 fi echo $FILE"を消します。" rm -f $FILE; else echo $SLEEP"秒休みます。" sleep $SLEEP fi done
テスト。書き込みスクリプトの起動。
$ sudo sh bin/syslog.sh 1秒休みます。 ... 1秒休みます。 /var/log/dblog/fulllog.2011.07.07.01.06.12を処理します。 /var/log/dblog/fulllog.2011.07.07.01.06.12を消します。 1秒休みます。 1秒休みます。 /var/log/dblog/fulllog.2011.07.07.01.06.14を処理します。 /var/log/dblog/fulllog.2011.07.07.01.06.14を消します。 1秒休みます。 /var/log/dblog/fulllog.2011.07.07.01.06.15を処理します。 /var/log/dblog/fulllog.2011.07.07.01.06.15を消します。 1秒休みます。 ...
別コンソールでログを書きこむ。
$ logger "hello1" $ logger "hello2" $ logger "hello3"
確認する。
mysql> select *,INET_NTOA(addr) from logs201107 order by id desc limit 10; +----+---------------------+-----------+------------+----------+-------+-----+---------+-----+----------+--------+-----------------+ | id | crtm | host | addr | facility | level | pri | program | pid | msghdr | msg | INET_NTOA(addr) | +----+---------------------+-----------+------------+----------+-------+-----+---------+-----+----------+--------+-----------------+ | 3 | 2011-07-07 01:06:15 | amdgentoo | 2130706433 | 1 | 5 | 13 | logger | 0 | logger: | hello3 | 127.0.0.1 | | 2 | 2011-07-07 01:06:14 | amdgentoo | 2130706433 | 1 | 5 | 13 | logger | 0 | logger: | hello2 | 127.0.0.1 | | 1 | 2011-07-07 01:06:12 | amdgentoo | 2130706433 | 1 | 5 | 13 | logger | 0 | logger: | hello1 | 127.0.0.1 | +----+---------------------+-----------+------------+----------+-------+-----+---------+-----+----------+--------+-----------------+ 3 rows in set (0.00 sec)
全部記録する場合 syslog-ng.conf の filter(f_database); の部分を消します。
記録が追いつかない場合、ログをファイルに書きこむやり方以外の方法もあります。
名前付きパイプ、プログラムに渡す、など。
もしくは別の言語などで複数の書き込み用のプロセスを起動します。
何かおかしい場合などは公式のマニュアルかソースを見ると古い情報を観る場合が減ります。
以下は詳細。
リモートの場合、日付はどうなる?
$ sudo /etc/init.d/syslog-ng reload syslog-ng |Your configuration file uses an obsoleted keyword, please update your configuration; keyword='use_time_recvd', change='Use R_ or S_ prefixed macros in templates or keep_timestamp(no)' syslog-ng |Error parsing main, syntax error, unexpected KW_USE_TIME_RECVD, expecting '}' in /etc/syslog-ng/syslog-ng.conf at line 13, column 9: syslog-ng | syslog-ng | use_time_recvd (yes); syslog-ng | ^^^^^^^^^^^^^^ syslog-ng | syslog-ng |syslog-ng documentation: http://www.balabit.com/support/documentation/?product=syslog-ng syslog-ng |mailing list: https://lists.balabit.hu/mailman/listinfo/syslog-ng syslog-ng | * Configuration error. Please fix your configfile (/etc/syslog-ng/syslog-ng.conf) [ !! ]
keep_timestamp(no) で $ISODATE などを全体的に変更する。古い場合 use_time_recvd(yes);
または $R_ISODATE, $S_ISODATE など手動で指定する。
古い場合 $MSG => $MSGONLY など。
$HOST or $SOURCEIP だけにするなど。$SOURCEIPは文字が良いなど。
($FACILITY_NUM, $LEVEL_NUM) or $PRI だけにするなど。もしくは$TAGにするなど。
($PROGRAM, $PID) or $MSGHDR だけにするなど。
フィルター変更
filter f_database { ... };or
フィルター無しなど。
log { source(src); source(kernsrc); source(net); destination(database); };
タブ区切りなどにして、insertする側で色々加工するなど。$MSGからindex対象の取り出し、文字コード統一など。
ログの取得方法変更 => 1秒ごとにファイル => 名前付きパイプ、デーモンの指定など。
ドキュメント。
/usr/share/doc/syslog-ng-3.2.4/syslog-ng.conf.doc.bz2 syslog-ng-3.2.4/contrib/syslog-ng.conf.docなど。
他の変数。
./lib/templates.c ./lib/logmsg.cなど。
テスト用設定の例。
template("FACILITY = '$FACILITY'\nFACILITY_NUM = '$FACILITY_NUM'\nPRIORITY = '$PRIORITY'\nLEVEL = '$LEVEL'\nLEVEL_NUM = '$LEVEL_NUM'\nTAG = '$TAG'\nTAGS = '$TAGS'\nBSDTAG = '$BSDTAG'\nPRI = '$PRI'\nDATE = '$DATE'\nFULLDATE = '$FULLDATE'\nISODATE = '$ISODATE'\nSTAMP = '$STAMP'\nYEAR = '$YEAR'\nYEAR_DAY = '$YEAR_DAY'\nMONTH = '$MONTH'\nMONTH_WEEK = '$MONTH_WEEK'\nMONTH_ABBREV = '$MONTH_ABBREV'\nMONTH_NAME = '$MONTH_NAME'\nDAY = '$DAY'\nHOUR = '$HOUR'\nMIN = '$MIN'\nSEC = '$SEC'\nWEEKDAY = '$WEEKDAY'\nWEEK_DAY = '$WEEK_DAY'\nWEEK_DAY_ABBREV = '$WEEK_DAY_ABBREV'\nWEEK_DAY_NAME = '$WEEK_DAY_NAME'\nWEEK = '$WEEK'\nTZOFFSET = '$TZOFFSET'\nTZ = '$TZ'\nUNIXTIME = '$UNIXTIME'\nR_DATE = '$R_DATE'\nR_FULLDATE = '$R_FULLDATE'\nR_ISODATE = '$R_ISODATE'\nR_STAMP = '$R_STAMP'\nR_YEAR = '$R_YEAR'\nR_YEAR_DAY = '$R_YEAR_DAY'\nR_MONTH = '$R_MONTH'\nR_MONTH_WEEK = '$R_MONTH_WEEK'\nR_MONTH_ABBREV = '$R_MONTH_ABBREV'\nR_MONTH_NAME = '$R_MONTH_NAME'\nR_DAY = '$R_DAY'\nR_HOUR = '$R_HOUR'\nR_MIN = '$R_MIN'\nR_SEC = '$R_SEC'\nR_WEEKDAY = '$R_WEEKDAY'\nR_WEEK_DAY = '$R_WEEK_DAY'\nR_WEEK_DAY_ABBREV = '$R_WEEK_DAY_ABBREV'\nR_WEEK_DAY_NAME = '$R_WEEK_DAY_NAME'\nR_WEEK = '$R_WEEK'\nR_TZOFFSET = '$R_TZOFFSET'\nR_TZ = '$R_TZ'\nR_UNIXTIME = '$R_UNIXTIME'\nS_DATE = '$S_DATE'\nS_FULLDATE = '$S_FULLDATE'\nS_ISODATE = '$S_ISODATE'\nS_STAMP = '$S_STAMP'\nS_YEAR = '$S_YEAR'\nS_YEAR_DAY = '$S_YEAR_DAY'\nS_MONTH = '$S_MONTH'\nS_MONTH_WEEK = '$S_MONTH_WEEK'\nS_MONTH_ABBREV = '$S_MONTH_ABBREV'\nS_MONTH_NAME = '$S_MONTH_NAME'\nS_DAY = '$S_DAY'\nS_HOUR = '$S_HOUR'\nS_MIN = '$S_MIN'\nS_SEC = '$S_SEC'\nS_WEEKDAY = '$S_WEEKDAY'\nS_WEEK_DAY = '$S_WEEK_DAY'\nS_WEEK_DAY_ABBREV = '$S_WEEK_DAY_ABBREV'\nS_WEEK_DAY_NAME = '$S_WEEK_DAY_NAME'\nS_WEEK = '$S_WEEK'\nS_TZOFFSET = '$S_TZOFFSET'\nS_TZ = '$S_TZ'\nS_UNIXTIME = '$S_UNIXTIME'\nSDATA = '$SDATA'\nMSGHDR = '$MSGHDR'\nSOURCEIP = '$SOURCEIP'\nSEQNUM = '$SEQNUM'\nMSG = '$MSG'\nMESSAGE = '$MESSAGE'\nHOST = '$HOST'\n\nHOST = '$HOST'\nHOST_FROM = '$HOST_FROM'\nMESSAGE = '$MESSAGE'\nPROGRAM = '$PROGRAM'\nPID = '$PID'\nMSGID = '$MSGID'\nSOURCE = '$SOURCE'\nLEGACY_MSGHDR = '$LEGACY_MSGHDR'\n---separate---\n")
結果。
$ logger "debug" $ sudo cat /var/log/dblog/fulllog.2011.07.07.01.30.48 FACILITY = 'user' FACILITY_NUM = '1' PRIORITY = 'notice' LEVEL = 'notice' LEVEL_NUM = '5' TAG = '0d' TAGS = '.source.src' BSDTAG = '5B' PRI = '13' DATE = 'Jul 7 01:30:48' FULLDATE = '2011 Jul 7 01:30:48' ISODATE = '2011-07-07T01:30:48+09:00' STAMP = 'Jul 7 01:30:48' YEAR = '2011' YEAR_DAY = '188' MONTH = '07' MONTH_WEEK = '1' MONTH_ABBREV = 'Jul' MONTH_NAME = 'July' DAY = '07' HOUR = '01' MIN = '30' SEC = '48' WEEKDAY = 'Thu' WEEK_DAY = '5' WEEK_DAY_ABBREV = 'Thu' WEEK_DAY_NAME = 'Thursday' WEEK = '27' TZOFFSET = '+09:00' TZ = '+09:00' UNIXTIME = '1309969848' R_DATE = 'Jul 7 01:30:48' R_FULLDATE = '2011 Jul 7 01:30:48' R_ISODATE = '2011-07-07T01:30:48+09:00' R_STAMP = 'Jul 7 01:30:48' R_YEAR = '2011' R_YEAR_DAY = '188' R_MONTH = '07' R_MONTH_WEEK = '1' R_MONTH_ABBREV = 'Jul' R_MONTH_NAME = 'July' R_DAY = '07' R_HOUR = '01' R_MIN = '30' R_SEC = '48' R_WEEKDAY = 'Thu' R_WEEK_DAY = '5' R_WEEK_DAY_ABBREV = 'Thu' R_WEEK_DAY_NAME = 'Thursday' R_WEEK = '27' R_TZOFFSET = '+09:00' R_TZ = '+09:00' R_UNIXTIME = '1309969848' S_DATE = 'Jul 7 01:30:48' S_FULLDATE = '2011 Jul 7 01:30:48' S_ISODATE = '2011-07-07T01:30:48+09:00' S_STAMP = 'Jul 7 01:30:48' S_YEAR = '2011' S_YEAR_DAY = '188' S_MONTH = '07' S_MONTH_WEEK = '1' S_MONTH_ABBREV = 'Jul' S_MONTH_NAME = 'July' S_DAY = '07' S_HOUR = '01' S_MIN = '30' S_SEC = '48' S_WEEKDAY = 'Thu' S_WEEK_DAY = '5' S_WEEK_DAY_ABBREV = 'Thu' S_WEEK_DAY_NAME = 'Thursday' S_WEEK = '27' S_TZOFFSET = '+09:00' S_TZ = '+09:00' S_UNIXTIME = '1309969848' SDATA = '' MSGHDR = 'logger: ' SOURCEIP = '127.0.0.1' SEQNUM = '' MSG = 'debug' MESSAGE = 'debug' HOST = 'amdgentoo' HOST = 'amdgentoo' HOST_FROM = 'amdgentoo' MESSAGE = 'debug' PROGRAM = 'logger' PID = '' MSGID = '' SOURCE = 'src' LEGACY_MSGHDR = 'logger: ' ---separate---
テーブル名をどうするか?
全部logs, logsYYYYMM, 名前はlogsでmysqlパーティショニングなど。
全部logsの場合でdeleteする場合myisamは重い。
logsYYYYMMなどは検索が面倒かもしれない。手動で検索する場合。
パーティショニングは手動インストールが必要かもしれない。
mysql> SHOW VARIABLES LIKE '%partition%'; +-------------------+-------+ | Variable_name | Value | +-------------------+-------+ | have_partitioning | NO | +-------------------+-------+ 1 row in set (0.00 sec)
24ヶ月先までテーブル作成。(seq 0 24 で今月分も含む。存在する場合、初期化される)
$ for num in $(seq 1 24); do cat bin/syslog.sql | sed "s/logs201107/logs$(date --date "${num} months" "+%Y%m")/g" | mysql -uroot syslog; done
mysql> show tables; +------------------+ | Tables_in_syslog | +------------------+ | logs201107 | | logs201108 | | logs201109 | | logs201110 | | logs201111 | | logs201112 | | logs201201 | | logs201202 | | logs201203 | | logs201204 | | logs201205 | | logs201206 | | logs201207 | | logs201208 | | logs201209 | | logs201210 | | logs201211 | | logs201212 | | logs201301 | | logs201302 | | logs201303 | | logs201304 | | logs201305 | | logs201306 | | logs201307 | +------------------+ 25 rows in set (0.00 sec)
追記: OS起動時に起動する例。
$ ll /usr/local/bin/sqlsyslogd -rwxr-xr-x 1 root root 507 2011-07-07 05:35:50 /usr/local/bin/sqlsyslogd*
ファイルは上記の例とおなしshスクリプト。
$ head -n1 /usr/local/bin/sqlsyslogd #!/bin/sh
起動してバックグラウンドに移動させる。
$ cat /etc/local.d/sqlsyslogd.start /usr/local/bin/sqlsyslogd > /dev/null 2>&1 &
確認する。
$ pstree -pal 9743 sqlsyslogd,9743 /usr/local/bin/sqlsyslogd └─sleep,10672 1
ディストリビューションごとに書く場所が違う。
$ cat /etc/rc.local #!/bin/sh # # This script will be executed *after* all the other init scripts. # You can put your own initialization stuff in here if you don't # want to do the full Sys V style init stuff. touch /var/lock/subsys/local
ダイレクトにデータベースに入れる機能があるように見えます。
これが良さそうなので、このページの例は使わないほうがいいかもしれません。
$ find ./syslog-ng-3.2.4/ -iname "*sql*" ./syslog-ng-3.2.4/tests/functional/test_sql.py ./syslog-ng-3.2.4/modules/afsql ./syslog-ng-3.2.4/modules/afsql/afsql.c ./syslog-ng-3.2.4/modules/afsql/afsql-grammar.h ./syslog-ng-3.2.4/modules/afsql/afsql-grammar.ym ./syslog-ng-3.2.4/modules/afsql/afsql.h ./syslog-ng-3.2.4/modules/afsql/afsql-grammar.c ./syslog-ng-3.2.4/modules/afsql/afsql-parser.c ./syslog-ng-3.2.4/modules/afsql/afsql-grammar.y ./syslog-ng-3.2.4/modules/afsql/afsql-parser.h ./syslog-ng-3.2.4/modules/afsql/afsql-plugin.c
$ grep -nriP "mysql|postgresql" ./syslog-ng-3.2.4/modules/afsql ./syslog-ng-3.2.4/modules/afsql/afsql.c:1146: self->type = g_strdup("mysql");
0 件のコメント:
コメントを投稿