越来越多大型的WEb服务使用DNS轮循来实现负载均衡:使用多个同样角色的服务器做前台的WEb服务,这大大方便了服务的分布规划和扩展性,但多个服务器的分布使得日志的分析统计也变得有些麻烦。如果使用webalizer等日志分析工具对每台机器分别做日志统计:1 会对数据的汇总带来很多麻烦,比如:统计的总访问量需要将SERVER1 SERVER2...上指定月份的数字相加。2 会大大影响统计结果中唯一访客数unique visits,唯一站点数unique sites的等指标的统计,因为这几个指标并非几台机器的代数相加。统一日志统计所带来的好处是显而易见的,但如何把所有机器的统计合并到一个统计结果里呢?首先也许会想:多个服务器能不能将日志记录到同一个远程文件里呢?我们不考虑使用远程文件系统记录日志的问题,因为带来的麻烦远比你获得的方便多的多……因此,要统计的多个服务器的日志还是:分别记录=>并通过一定方式定期同步到后台=>合并=>后用日志分析工具来进行分析。首先,要说明为什么要合并日志:因为webalizer没有将同一天的多个日志合并的功能先后运行
webalizer log1 webalizer log2webalizer log3 这样最后的结果是:只有log3的结果。能不能将log1<
[31/Mar/2002:59:59:59 0800][31/Mar/2002:23:59:59 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800] 要知道[01/Apr/2002:00:00:00 这个字段是不可以进行“跨天排序”的。因为日期中使用了dd/mm/yyyy,月份还是英文名,如果按照字母排序,很有可能是这样的结果:排序导致了日志的错误
[01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][01/Apr/2002:00:00:00 0800][31/Mar/2002:59:59:59 0800][31/Mar/2002:59:59:59 0800][31/Mar/2002:23:59:59 0800][31/Mar/2002:59:59:59 0800][31/Mar/2002:23:59:59 0800] 这些跨天过程中的非正常数据对于webalizer等分析工具来说简直就好像是吃了一个臭虫一样,运行的结果是:它可能会把前一个月所有的数据都丢失!因此这样的数据会有很多风险出现在处理上月最后一天的数据的过程中。问题的解决有几个思路:1 事后处理:。所以一个事后的处理的方法是:用grep命令在每月第1天将日志跨月的日志去掉,比如:
grep -v '01/Apr' access_log_04_01 > access_log_new 修改SORT后的日志:所有跨天的数据去掉。也许对日志的事后处理是一个途径,虽然sort命令中有对日期排序的特殊选项 -M(注意是:大写M),可以让指定字段按照英文月份排序而非字母顺序,但对于apache日志来说,用SORT命令切分出月份字段很麻烦。(我尝试过用 '/'做分割符,并且使用“月份” “年:时间”这两个字段排序)。虽然用一些pERL的脚本肯定可以实现,但最终我还是放弃了。这不符合系统管理员的设计原则:通用性。并且你需要一直问自己:有没有更简单的方法呢?还有就是将日志格式改成用TIMESTAMp(象SQUID的日志就没有这个问题,它的日志本身就是使用TIMESTAMp做时间时间戳的),但我无法保证所有的日志工具都能识别你在日期这个字段使用了特别的格式。2 优化数据源:最好的办法还是优化数据源。将数据源保证按天轮循,同一天的日志中的数据都在同一天内。这样以后你无论使用什么工具(商业的,免费的)来分析日志,都不会因为日志复杂的预处理机制受到影响。首先可能会想到的是控制截取日志的时间:比如严格从0点开始截取日志,但在子夜前1分钟还是后一分钟开始截取是没有区别的,你仍然无法控制一个日志中有跨2天记录的问题,而且你也无法预测日志归档过程使用的时间。 因此必须要好好考虑一下使用日志轮循工具的问题,这些日志轮循工具要符合:1 不中断WEb服务:不能停apache=>移动日志=>重启apache2 保证同一天日志能够按天轮循:每天一个日志00:00:00-23:59:593 不受apache重启的影响:如果apache每次重启都会生成一个新的日志是不符合要求的4 安装配置简单首先考虑了apache/bin目录下自带的一个轮循工具:rotatelogs 这个工具基本是用来按时间或按大小控制日志的,无法控制何时截断和如何按天归档。然后考虑logrotate后台服务:logrotate是一个专门对各种系统日志(syslogd,mail)进行轮循的后台服务,比如SYSTEM LOG,但其配置比较复杂,放弃,实际上它也是对相应服务进程发出一个-HUp重启命令来实现日志的截断归档的。在apache的FAQ中,推荐了经过近2年发展已经比较成熟的一个工具cronolog:安装很简单:
configure=>make=> make install 他的一个配置的例子会让你了解它有多么适合日志按天轮循:对httpd.conf做一个很小的修改就能实现:
TransferLog '|/usr/sbin/cronolog /web/logs/%Y/%m/%d/access.log'ErrorLog '|/usr/sbin/cronolog /web/logs/%Y/%m/%d/errors.log' 然后:日志将写入
/web/logs/2002/12/31/access.log/web/logs/2002/12/31/errors.log 午夜过后:日志将写入
/web/logs/2003/01/01/access.log/web/logs/2003/01/01/errors.log 而2003 2003/01 和 2003/01/01 如果不存在的话,将自动创建所以,只要你不在0点调整系统时间之类的话,日志应该是完全按天存放的(00:00:00-23:59:59),后面日志分析中:[31/Mar/2002:15:44:59这个字段就和日期无关了,只和时间有关。测试:考虑到系统硬盘容量,决定按星期轮循日志apache配置中加入:
#%w weekdayTransferLog '|/usr/sbin/cronolog /path/to/apache/logs/%w/access_log' 重启apache后,除了原来的CustomLog /path/to/apche/logs/access_log继续增长外,系统log目录下新建立了 3/目录(测试是在周3),过了一会儿,我忽然发现2个日志的增长速度居然不一样!分别tail了2个日志才发现:我设置CustomLog使用的是combined格式,就是包含(扩展信息的),而TransferLog使用的是缺省日志格式,看了apache的手册才知道,TransferLog是用配置文件中离它自己最近的一个格式作为日志格式的。我的httpd.conf里写的是:
LogFormat ..... combinedLogFormat ... common...CustomLog ... combinedTransferLog ... 所以TrasferLog日志用的是缺省格式,手册里说要让TRANSFER日志使用指定的格式需要:
LogFormat '%h %l %u %t \'%r\' %>s %b \'%{Referer}i\' \'%{User-Agent}i\''TransferLog '|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log' 重启,OK,日志格式一样了。这样的设置结果其实是同时在logs目录下分别记录2个日志access_log和%w/access_log,能不能只记录%w/下的日志那?查apache手册,更简单的方法:直接让CustomLog输出到cronolog归档日志,并且还能指定格式。
CustomLog '|/usr/local/sbin/cronolog /path/to/apache/logs/%w/access_log' combined 最后是一个日志同步的问题。任务:每天凌晨找到前1天的日志,另存一个文件准备发送到服务器上。比如我要保留前1周的日志:每天复制前1天的日志到指定目录,等待日志服务器来抓取:
/bin/cp /path/to/logs/`date -v-1d %w`/access_log /path/to/sync/logs/access_yesterday 在FREEbSD上使用以下命令
date -v-1d %w 注释:-v-1d: 前1天,而在LINUX上这个选项应该是date -d yesterday %w: weekday,由于使用的都是标准时间函数库,所有工具中的WEEKDAY定义都是一样的 0-6 => 周日-周六注意:写到CRONTAb里的时候'%'前面需要加一个'\'转义:每天0点5分进行一次日志归档
5 0 * * * /bin/cp /path/to/logs/`date -v-1d \%w`/access_log /path/to/for_sync/logs/access_yesterday 首次开始cronolog日志统计是周3,一周以后日志又将轮循回3/access_log但这次日志是追加到3/access_log还是重新创建一个文件呢?>>access_log or >access_log?我测试的结果是日志将被追加:
[01/Apr/2002:23:59:59 0800][01/Apr/2002:23:59:59 0800][08/Apr/2002:00:00:00 0800][08/Apr/2002:00:00:00 0800] 肯定是不希望每次日志还带着上周的数据的并重复统计一次的(虽然对结果没影响),而且这样%w/下的日志不是也越来越多了吗?解决方法1 把每天的cp改成mv解决方法2 每天复制完成后:删除6天以前的access_log日志
find /path/to/apache/logs -name access_log -mtime 6 -exec rm -f {}\; 多保留几天的日志还是有必要的:万一日志分析服务器坏了一天呢?总结:1 用 cronolog 干净,安全地轮循日志2 用 sort -m 排序合并多个日志。