这个公告的东西哇,说来话长,250个汉字根本不够我发挥嘛;既然这样,那就不发挥了!o(∩_∩)o...哈哈

多服务器的日志合并统计——apache日志的cronolog轮循

上一篇 / 下一篇  2007-11-19 21:09:26 / 个人分类:数据分析

内容摘要:你完全不必耐心地看完下面的所有内容,因为结论无非以下2点:
mY+G~8yL?-Q01 用 cronolog 干净,安全地轮循apache“日”志
&_9p!h2MO4b02 用 sort -m 合并排序多个日志19楼空间"i;~4xm M.H*o Xd
19楼空间Es,er#i!K
根据个人的使用经历:
A%DM2d3oLCp01 先介绍apache日志的合并方法;
6Q1}.TSm1Ay02 然后根据由此引出的问题说明日志轮循的必要性和解决方法,介绍如何通过cronolog对apache日志进行轮循;
#ld,EZ3ew0中间有很多在设计日志合并过程中一些相关工具的使用技巧和一些尝试的失败经历……
9Ol#?ep isJ8@0我相信解决以上问题的路径不止这一条途径,以下方案肯定不是最简便或者说成本最低的,希望能和大家有更多的交流。19楼空间4a$a y cP ].U;^q,D

iJ PC?8g\019楼空间Z'W gs}Q

多服务器日志合并统计的必要性

越来越多大型的WEB服务使用DNS轮循来实现负载均衡:使用多个同样角色的服务器做前台的WEB服务,这大大方便了服务的分布规划和扩展性,但多个服务 器的分布使得日志的分析统计也变得有些麻烦。如果使用webalizer等日志分析工具对每台机器分别做日志统计:19楼空间0V1exb)yOy\
1 会对数据的汇总带来很多麻烦,比如:统计的总访问量需要将SERVER1 SERVER2...上指定月份的数字相加。19楼空间mr ]|&h*R
2 会大大影响统计结果中唯一访客数unique visits,唯一站点数unique sites的等指标的统计,因为这几个指标并非几台机器的代数相加。
&J+D#lVn e;n019楼空间7`Y]^xLv
统一日志统计所带来的好处是显而易见的,但如何把所有机器的统计合并到一个统计结果里呢?19楼空间4w~1NbM6C O
首先也许会想:多个服务器能不能将日志记录到同一个远程文件里呢?我们不考虑使用远程文件系统记录日志的问题,因为带来的麻烦远比你获得的方便多的多……19楼空间 hv]f#_{a hF
因此,要统计的多个服务器的日志还是:分别记录=>并通过一定方式定期同步到后台=>合并=>后用日志分析工具来进行分析。19楼空间Cv)O#u0Y0]4C
19楼空间 M.WL]L iJ`K
首先,要说明为什么要合并日志:因为webalizer没有将同一天的多个日志合并的功能19楼空间p-]%w(?;T)W t
先后运行
|#RN%y)qn:xAD ?S0webalizer log1
6|f0T3v3J \QX4k1@F0webalizer log219楼空间 o_G |A)emk!J
webalizer log3
4z"FKpu U0这样最后的结果是:只有log3的结果。
!P(s4E aMj Lgn0
v-o{V7L B6R0能不能将log1<<log2<<log3简单叠加呢?19楼空间JtH"g F4X"Sb!~1i@
因为一个日志的分析工具不是将日志一次全部读取后进行分析,而且流式的读取日志并按一定时间间隔,保存阶段性的统计结果。因此时间跨度过大(比如2条日志 间隔超过5分钟),一些日志统计工具的算法就会将前面的结果“忘掉”。因此, log1<<log2<<log3直接文件连接的统计结果还是:只有log3的统计结果。19楼空间4f7_H%]^0?9Z k2gc

ueR;~Q$t4v0

多台服务日志合并问题:把多个日志中的记录按时间排序后合并成一个文件

典型的多个日志文件的时间字段是这样的:
:pk^~!f ECH+F0log1 log2 log319楼空间.[b't?A#A
00:15:00 00:14:00 00:11:0019楼空间5n0Bwsj5w.s*Xg Y%AC
00:16:00 00:15:00 00:12:0019楼空间/e`4s OW
00:17:00 00:18:00 00:13:00
.w9~#gm!Yr"g1O?000:18:00 00:19:00 00:14:00
i@*N}c,^3f$V?i014:18:00 11:19:00 10:14:0019楼空间c}D#g4d+p.Y
15:18:00 17:19:00 11:14:0019楼空间i&v1u I2Nhg0Z7A])\P u)N+L
23:18:00 23:19:00 23:14:00
6^z2Q.]#fM0
q(`"x3K5C7NT0日志合并必须是按时间将多个日志的交叉合并。合并后的日志应该是:
f*lo vc[z/|J000:15:00 来自log1
M"vJ8V;U:C000:15:00 来自log2
A lh0T W oO000:16:00 来自log1
Jm{tnC'd4or:XV000:17:00 来自log3
'p2@&Xq:eo(h(^000:18:00 来自log219楼空间Y4\!M^G7c
00:19:00 来自log1
y#[2exW+Uv0....19楼空间F]e6ZZ1CP6_n0m

*D([%OZ T)F0如何合并多个日志文件?19楼空间 qc*z4C3[F l&X%L
下面以标准的clf格式日志(apache)为例:
C7j6NJ%w9@0apche的日志格式是这样的:
]'C.{\5S6T2A#|1_\h0%h %l %u %t \"%r\" %>s %b
uzb0Zk4C8S{zf0具体的例子:
U5Fj.^0BL"j0111.222.111.222 - - [03/Apr/2002:10:30:17 +0800] "GET /index.html HTTP/1.1" 200 41919楼空间 \o1o6tg)V s

H \7tE#_)Y3T }b0最简单的想法是将日志一一读出来,然后按日志中的时间字段排序19楼空间"My Em"H r]G7n
cat log1 log2 log3 |sort -k 4 -t " "
/vj;aVo6j9C0注释:
%s.n Hr+Rn@*u)y7o_ N0-t " ": 日志字段分割符号是空格19楼空间e5A1L8d0r\2|#L
-k 4: 按第4个字段排序,也就是:[03/Apr/2002:10:30:17 +0800] 这个字段19楼空间'K~9f4{6vW}
-o log_all: 输出到log_all这个文件中
i u9`_+o(f0
;_-^9Vc$KT0但这样的效率比较低,要知道。如果一个服务已经需要使用负载均衡,其服务的单机日志条数往往都超过了千万级,大小在几百M,这样要同时对多个几百M的日志 进行排序,机器的负载可想而之……19楼空间5|5C"N^.y2D*\.T
其实有一个优化的途径,要知道:即使单个日志本身已经是一个“已经按照时间排好序“的文件了,而sort对于这种文件的排序合并提供了一个优化合并算法: 使用 -m merge合并选项,19楼空间 P1P YX0Bd z3]
因此:合并这样格式的3个日志文件log1 log2 log3并输出到log_all中比较好方法是:19楼空间L&pe q l
sort -m -t " " -k 4 -o log_all log1 log2 log3
!y$`7[%gHG0注释:19楼空间5? Q _\ m;u%X&Ix o-T
-m: 使用 merge优化算法
G[ O:qi}0
YiTs+_0注意:合并后的日志输出最好压缩以后再发给webalizer处理
0d2L,@F0W~(~0有的系统能处理2G的文件,有的不能。有的程序能处理大于2G的文件,有的不能。尽量避免大于2G的文件,除非确认所有参与处理的程序和操作系统都能处理 这样的文件。所以输出后的文件如果大于2G,最好将日志gzip后再发给webalizer处理:大于2G的文件分析过程中文件系统出错的可能性比较大, 并且gzip后也能大大降低分析期间的I/O操作。
up$S:?T-fg US9A-{0
:nVH#kc2O0日志的按时间排序合并就是这样实现的。
9@4PN8X9Og019楼空间(p$b$G&E+X.A

日志的轮循机制

让我们关心一下数据源问题:webalizer其实是一个按月统计的工具,支持增量统计:因此对于大型的服务,我可以按天将apache的日志合并后送给 webalizer统计。WEB日志是如何按天(比如每天子夜00:00:00)截断呢?19楼空间}(gGw L ig
如果你每天使用crontab:每天0点准时将日志备份成access_log_yesterday19楼空间"lI~["}A2v
mv /path/to/apache/log/access_log /path/to/apache/log/access_log_yesterday19楼空间H\WJ`3D^x$h
的话:你还需要:马上运行一下:apache restart 否则:apache会因为的日志文件句柄丢失不知道将日志记录到哪里去了。这样归档每天子夜重启apache服务会受到影响。19楼空间"wiw%F Q3p
比较简便不影响服务的方法是:先复制,后清空19楼空间DE/P3TJ's@}^g&g
cp /path/to/apache/log/access_log /path/to/apache/log/access_log_yesterday
4Z&hrT'vqD+M$h(X0echo >/path/to/apache/log/access_log
#cBae)w]W019楼空间-hzJ-[oU|\3m2V)m&Vc
严肃的分析员会这样做发现一个问题:19楼空间+A!f0L!a)U%J
但cp不可能严格保证严格的0点截断。加入复制过程用了6秒,截断的access_log_yesterday日志中会出现复制过程到00:00:06期 间的日志。对于单个日志统计这些每天多出来几百行日志是没有问题的。但对于多个日志在跨月的1天会有一个合并的排序问题:
M;D7gH(^0[31/Mar/2002:59:59:59 +0800]
Zc]#v0B(m0[31/Mar/2002:23:59:59 +0800]19楼空间&Fjv.D$M'x
[01/Apr/2002:00:00:00 +0800]19楼空间'~yz6I sw ?
[01/Apr/2002:00:00:00 +0800]
oq noRQ019楼空间;Ib;c Rx*M0Au tI{
要知道[01/Apr/2002:00:00:00 这个字段是不可以进行“跨天排序”的。因为日期中使用了dd/mm/yyyy,月份还是英文名,如果按照字母排序,很有可能是这样的结果:排序导致了日志 的错误
,pU1H"mV0[01/Apr/2002:00:00:00 +0800]19楼空间%p.d[V5~\P
[01/Apr/2002:00:00:00 +0800]
6E#uR'a&nb+_0[01/Apr/2002:00:00:00 +0800]
C_o:svp7y3A0[01/Apr/2002:00:00:00 +0800]
f!f[%J3n(J~ |j0[01/Apr/2002:00:00:00 +0800]
K(Vf)S-JL)V0[01/Apr/2002:00:00:00 +0800]19楼空间-U1I8wJ"O
[01/Apr/2002:00:00:00 +0800]19楼空间%D!Ip-t'Mv9d
[31/Mar/2002:59:59:59 +0800]19楼空间j&b0[cY'V(Wl @x
[31/Mar/2002:59:59:59 +0800]
GLHl'Z a9i0Yq+A0[31/Mar/2002:23:59:59 +0800]19楼空间O i`"g7Ot
[31/Mar/2002:59:59:59 +0800]
3^ ad AT }H/yQ0[31/Mar/2002:23:59:59 +0800]19楼空间FvEB|Y

7[B7U7{Z&t0这些跨天过程中的非正常数据对于webalizer等分析工具来说简直就好像是吃了一个臭虫一样,运行的结果是:它可能会把前一个月所有的数据都丢失!因 此这样的数据会有很多风险出现在处理上月最后一天的数据的过程中。19楼空间.hXZ Jm n
19楼空间(})m0T dt C
问题的解决有几个思路:19楼空间e\(aD5Qe:c
1 事后处理:
EdXi8Gv3s3iD0。所以一个事后的处理的方法是:用grep命令在每月第1天将日志跨月的日志去掉,比如:
+JQ*O U,s0grep -v "01/Apr" access_log_04_01 > access_log_new19楼空间Ar8K5h'P6Q zgJT

T^3nA0h+kh0修改SORT后的日志:所有跨天的数据去掉。也许对日志的事后处理是一个途径,虽然sort命令中有对日期排序的特殊选项 -M(注意是:大写M),可以让指定字段按照英文月份排序而非字母顺序,但对于apache日志来说,用SORT命令切分出月份字段很麻烦。(我尝试过用 "/"做分割符,并且使用“月份” “年:时间”这两个字段排序)。虽然用一些PERL的脚本肯定可以实现,但最终我还是放弃了。这不符合系统管理员的设计原则:通用性。 并且你需要一直问自己:有没有更简单的方法呢?19楼空间qa,K(T/Y)V,V5V
还有就是将日志格式改成用TIMESTAMP(象SQUID的日志就没有这个问题,它的日志本身就是使用TIMESTAMP做时间时间戳的),但我无法保 证所有的日志工具都能识别你在日期这个字段使用了特别的格式。19楼空间Zd*?Y-v:a+J4Y
19楼空间8W'gBR8K6[%v
2 优化数据源:19楼空间-J G,L5KB'T,] {
最好的办法还是优化数据源。将数据源保证按天轮循,同一天的日志中的数据都在同一天内。这样以后你无论使用什么工具(商业的,免费的)来分析日志,都不会 因为日志复杂的预处理机制受到影响。19楼空间 d9P9fz[ yXX'H
19楼空间W d!uI Z
首先可能会想到的是控制截取日志的时间:比如严格从0点开始截取日志,但在子夜前1分钟还是后一分钟开始截取是没有区别的,你仍然无法控制一个日志中有跨 2天记录的问题,而且你也无法预测日志归档过程使用的时间。
+B?i^R#H8s#LY'q0因此必须要好好考虑一下使用日志轮循工具的问题,这些日志轮循工具要符合:19楼空间 Q|2_WCo+M!_(L P
1 不中断WEB服务:不能停apache=>移动日志=>重启apache19楼空间? m"kx!B O
2 保证同一天日志能够按天轮循:每天一个日志00:00:00-23:59:59
k0~Q U i!Ze}zC03 不受apache重启的影响:如果apache每次重启都会生成一个新的日志是不符合要求的
9Nwt'j rB3w:N#a~P3g04 安装配置简单19楼空间;N,h3f8`1v(b,|;D%z Hq%{
19楼空间UzACm!B
首先考虑了apache/bin目录下自带的一个轮循工具:rotatelogs 这个工具基本是用来按时间或按大小控制日志的,无法控制何时截断和如何按天归档。19楼空间s WN!x'Z+mA
然后考虑logrotate后台服务:logrotate是一个专门对各种系统日志(syslogd,mail)进行轮循的后台服务,比如SYSTEM LOG,但其配置比较复杂,放弃,实际上它也是对相应服务进程发出一个-HUP重启命令来实现日志的截断归档的。
$? ~KbK @,B s8Q9S019楼空间7u:t;j.G5V,F
在apache的FAQ中,推荐了经过近2年发展已经比较成熟的一个工具cronolog:安装很简单:configure=>make=> make install19楼空间 p!l:b+_w4mEo r
19楼空间Rn#_g(FJ
他的一个配置的例子会让你了解它有多么适合日志按天轮循:对httpd.conf做一个很小的修改就能实现:
a5]t Y!tIl;}\I0TransferLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log"19楼空间'n$q&E$l%E)yC5T k*t
ErrorLog "|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log"19楼空间zm&`Pz3Tt7f3LeL k

9Z:f-F G4L0然后:日志将写入
OtjlZ$xj6j,o^}W0/web/logs/2002/12/31/access.log
2C'XT5Ba0/web/logs/2002/12/31/errors.log19楼空间 \[Gw6Np
午夜过后:日志将写入
~$uJ#NLLM^k7w"Q0/web/logs/2003/01/01/access.log
6cw!O)r8{MBs h0/web/logs/2003/01/01/errors.log
5k$F0d,Hz0xm}0而2003 2003/01 和 2003/01/01 如果不存在的话,将自动创建19楼空间P7U+mJe
19楼空间/yKHAZV[p7j
所以,只要你不在0点调整系统时间之类的话,日志应该是完全按天存放的(00:00:00-23:59:59),后面日志分析中: [31/Mar/2002:15:44:59这个字段就和日期无关了,只和时间有关。19楼空间6dTIK"z\*O
19楼空间$}NRA_p$auN
测试:考虑到系统硬盘容量,决定按星期轮循日志19楼空间#z)F5fm[la
apache配置中加入:
u2n A!I*R i o0#%w weekday19楼空间 Q#`G:p _#Uc
TransferLog "|/usr/sbin/cronolog /path/to/apache/logs/%w/access_log"19楼空间R!v'MMU6Q6`2n2k!{
19楼空间 gu:i1Ma#j){Z
重启apache后,除了原来的CustomLog /path/to/apche/logs/access_log继续增长外,系统log目录下新建立了 3/目录(测试是在周3),过了一会儿,我忽然发现2个日志的增长速度居然不一样!19楼空间 V@yi jj#i#}
分别tail了2个日志才发现:
bi4?x9RVt.~0我设置CustomLog使用的是combined格式,就是包含(扩展信息的),而TransferLog使用的是缺省日志格式,看了apache的手 册才知道,TransferLog是用配置文件中离它自己最近的一个格式作为日志格式的。我的httpd.conf里写的是:19楼空间"SoH[ n e\
LogFormat ..... combined19楼空间 TZ?PX(HVk] qx!N
LogFormat ... common19楼空间Ni;}.N+t9E*Cp"~
...19楼空间0w;E$`E?
CustomLog ... combined19楼空间B4H)_/XMw(~
TransferLog ...19楼空间 S0?4q"Gto]
19楼空间a7X(k$[l\!d"A&|-D*Pm
所以TrasferLog日志用的是缺省格式,手册里说要让TRANSFER日志使用指定的格式需要:19楼空间N)|+^3lL/V.Pc Z&w
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\""
F F/j;c:C&NI0TransferLog "|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log"
-A`3N'NT3Xq0
aNNzdm0重启,OK,日志格式一样了。19楼空间K8x6j9h Nqyy
这样的设置结果其实是同时在logs目录下分别记录2个日志access_log和%w/access_log,能不能只记录%w/下的日志那?19楼空间{9]#Ld`9U)y3i|'g$O
查apache手册,更简单的方法:直接让CustomLog输出到cronolog归档日志,并且还能指定格式。
wv9`z@ W0Ck/J#[0CustomLog "|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log" combined19楼空间 X0}7wv6}!H5q({
19楼空间)]4cl _N+|
最后是一个日志同步的问题。
.^B-O3oG^4U.{VG/V0
7i`"s7[$WNQ%am nY0任务:每天凌晨找到前1天的日志,另存一个文件准备发送到服务器上。19楼空间B\Vs_)c9ICH!AI
比如我要保留前1周的日志:每天复制前1天的日志到指定目录,等待日志服务器来抓取:
f @ PFE9]H KI+P2sGe0/bin/cp -f /path/to/apache/logs/`date -v-1d +%w`/access_log /path/for/backup/logs/access_log_yesterday
O$G(gm*b0
Dt _7SnI7M0在FREEBSD上使用以下命令19楼空间~1^YOnV Z
date -v-1d +%w19楼空间9Aa!~-j_hji @uF
注释:19楼空间+S4Yc_3f4l1^a
-v-1d: 前1天,而在GNU/Linux上这个选项应该是date -d yesterday
/gmtj5C,va0B1J7^0+%w: weekday,由于使用的都是标准时间函数库,所有工具中的WEEKDAY定义都是一样的 0-6 => 周日-周六
})CvJft0
BXN_*f(F0注意:
o;uo t }K0写到CRONTAB里的时候"%"前面需要加一个"\"转义:每天0点5分进行一次日志归档,19楼空间0g U x%XN/Nd
另外一个问题就是在cront中需要用:rm -f {} ; 而不是rm -f {}\;19楼空间%oh4?C!G"I
5 0 * * * /bin/cp /path/to/logs/`date -v-1d +\%w`/access_log /path/to/for_sync/logs/access_yesterday
u| K+J&a m9U6U @037 10 * * * /usr/bin/find /home/apache/logs/ -name access_log -mtime +1 -exec /bin/rm -f {} ;19楼空间Z5wv,G`)h

首次开始cronolog日志统计是周3,一周以后日志又将轮循回3/access_log
Je:z3e&Fh0但这次日志是追加到3/access_log还是重新创建一个文件呢?>>access_log or >access_log?19楼空间!B!HJU1rH
我测试的结果是日志将被追加:19楼空间F7|@-S-JJI {g:bO
[01/Apr/2002:23:59:59 +0800]
9r0e.H0h?pD)DW-s0[01/Apr/2002:23:59:59 +0800]
'Mu%ML7?FP9P H0[08/Apr/2002:00:00:00 +0800]19楼空间(G7{5C1Ee
[08/Apr/2002:00:00:00 +0800]19楼空间1bB7vJY3_m K
19楼空间2d+h0jn#mTn
肯定是不希望每次日志还带着上周的数据的并重复统计一次的(虽然对结果没影响),而且这样%w/下的日志不是也越来越多了吗?
/d2I;{$c t2jQ0解决方法1 把每天的cp改成mv
B3si3gd9\BhZ0解决方法2 每天复制完成后:删除6天以前的access_log日志
ir(}C j;W2P#_+~0find /path/to/apache/logs -name access_log -mtime +6 -exec rm -f {}\;
9I*qA0LP vc0多保留几天的日志还是有必要的:万一日志分析服务器坏了一天呢?

以下是把apache安装在/home/apache下每天统计的一个脚本文件:
Nx?1~-t*Oc0#!/bin/sh
$N4?@I8@9]0
:otZO H P0#backup old log
J|@f f-j'U0/bin/cp -f /home/apache/logs/`date -d yesterday +%w`/access_log /home/apache/logs/access_log_yesterday19楼空间6ff5rpqE
19楼空间%r} MsZ4}-c
#remove old log19楼空间 CF.H2niN5\
/usr/bin/find /home/apache/logs -name access_log -mtime +6 -exec rm -f {}\;
)s&A+s5{X0
9is1pzA+O`(A&V0#analysis with webalizer19楼空间4l-@-{I I9J;Q](?zw_
/usr/local/sbin/webalizer
9[6X5gY0Cd0
o:~l*PZ-ZC#X)u6w e0总结:
:qZ:i&V4X:Ocv(n01 用 cronolog 干净,安全地轮循日志19楼空间T?:m7Y n
2 用 sort -m 排序合并多个日志
IS'[9mrFJ:K;[(N0
#} d5WW8e a7X019楼空间T%Tjs5FA
参考资料:19楼空间4])^+p$`xk'U1rJ2n

-iQ`y#l5m0日志分析统计工具:19楼空间 SE!V9}c|J
http://directory.google.com/Top/Computers/Software/Internet/Site_Management/Log_Analysis/

Apche的日志设置:
lHAjw1es5`0http://httpd.apache.org/docs/mod/mod_log_config.html

Apache的日志轮循:
1X xn8["o'R|[h0http://httpd.apache.org/docs/misc/FAQ.html#rotate19楼空间Y,R E$g'OW

.O/WG E"Q:n"y0Cronolog19楼空间? z,i8l0{||"K}3k U
http://www.cronolog.org19楼空间 |J,{2]QY$i)~v

Webalizer19楼空间#E7p~$n*gf_
http://www.mrunix.net/webalizer/
+KJ g5]|@)L e0Webalzer的Windows版
_(z(y+U8@'f\U2|0http://www.medasys-lille.com/webalizer/
0LC%h8qr#C0

AWStats的使用简介19楼空间!L6["|8a$meb*h0E U
http://www.chedong.com/tech/awstats.html


TAG: 日志合并 车东

咔嚓网-数码冲印 引用 删除 kacawang   /   2009-07-07 11:28:29
5
龙腾四海,凤舞九天 引用 删除 gfwan1314   /   2007-11-19 21:16:20
 

评分:0

我来说两句
请谨慎发帖,本网站会记录您的IP地址。请注意,根据我国法律,网站会将有关您发帖内容、发帖时间以及您发帖时的IP地址的记录保留至少60天,并且只要接到合法请求,即会将这类信息提供给有关政府机构。

显示全部

:loveliness: :handshake :victory: :funk: :time: :kiss: :call: :hug: :lol :'( :Q :L ;P :$ :P :o :@ :D :( :)

日历

« 2009-07-11  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 65459
  • 日志数: 75
  • 图片数: 2
  • 文件数: 2
  • 书签数: 3
  • 建立时间: 2007-02-26
  • 更新时间: 2008-03-15

RSS订阅

Open Toolbar