情景描述:
公司web服务器分为三个集群:前台(包括www、news、m等站点);图片(包括img、static等站点);后台(包括user、interface等站点)。这种情况下如何使用awstats进行日志分析呢?
这个需求我们很容易想到其中的几个“关键点”
1、如何将各台web server上的站点日志拷贝到awstats server上的合适位置以备处理呢?这好说,写脚本用scp或者rsync嘛!ok,再想一步,如何在server数量或者server上站点发生变化时,脚本依然能够正确的完成任务呢?这就要各server上关于日志名称、日志及其备份目录、日志轮转等方面做统一约定了,脚本按照这个约定才能“以不变应万变”。
2、一个站点的访问日志势必会有多份,awstats如何处理呢?还好这一点awstats已经帮我们想好了,在awstats配置文件里关于“LogFile=”部分的注释已经写得很清楚。
3、这么多站点,最好有一个统一的入口页面,而且增减站点入口要简单,用着才方便。
基于以上几点,本文分享一种思路,若有不当之处,还请不吝指教。
文章分四个部分:前提及约定;awstats配置要点和FastCGI方式配置;集中展示页面(JavaScript实现);日志收集处理脚本
一、前提及约定
先看下我的约定(其实某些约定即使在本文之外也是很有必要的,例如1、2。脚本的正常运行依赖于这些约定):
1、日志命名:如www.abc.com访问日志命名为www.access.log;日志存放位置:当前的日志存在于/nginx_log目录,日志备份存储于/nginx_log/backup。看下图就一目了然了
2、日志轮转:我的web server为nginx,通过日志切割脚本自动在0点重新生成日志,并将旧日志文件以前一天的日期为后缀命名(例如“p_w_picpaths.access.log.2015-12-02”)移动到日志备份目录。
看下日志切割脚本(在每台web server定时0点执行)
cat rotate_nginx_logs.sh
#!/bin/sh logs_path="/nginx_log" ###日志存放路径 logs_bak_dir="/nginx_log/backup" ###日志备份目录 yesterday=`date -d "1 day ago" +%` pid_file=`cat /usr/local/nginx/nginx.pid` ###nginx pid 文件 cd $logs_path for log in `ls *.log`;do mv $log $logs_bak_dir/$log.$yesterday;done ###重命名日志文件 kill -USR1 $pid_file ###告知nginx重新生成日志 cd $logs_bak_dir find . -mtime +5|xargs rm -f ###删除backup目录下超过5天的备份
3、每天凌晨自动完成这一系列任务, 页面最新可显示昨日的分析结果
4、各站点日志文件拉取到awstats server后的存储形式
5、awstats server设置对所有相关web server的免秘钥登陆,以便拉取日志
二、awstats配置要点和FastCGI方式配置
这里不展开详细的安装步骤,只说明一些配置选项以及如何配置动态模式。
awstats有两种方式展示分析结果:一种是命令行生成html格式的分析页面;另一种是在浏览器通过向CGI网关传递参数来动态生成分析结果。
其实在原理上,这两种形式都需要“perl awstats.pl -config=mysite.conf -update”命令定时更新生成指定站点的“数据文件”(即经过awstats.pl分析日志生成的中间文件),然后可以分两种方法(对中间文件进行处理)生成我们看到的分析页面:
1、通过“perlawstats.pl -config=www.conf -output -staticlinks > www.html”命令生成html文件用于展示
2、web服务器通过FastGCI调用类似“http://awstats.abc.com/cgi-bin/awstats.pl?config=/usr/local/services/awstats-7.4/etc/www.conf”的url在访问时动态生成分析页面。
两种方式各有优缺:第一种定时生成html文件,访问时页面加载快,但是页面布局使用起来不方便也不美观;第二种在打开页面时需要临时处理“数据文件”生成html,页面加载速度根据“数据文件”大小不同会有不同程度延迟,但是动态形式的页面布局看着舒服用着顺手(所以我选择fastcgi模式)。
fastcgi模式页面如下图所示
来看下我的awstats目录,其中我增加了三个目录,如下图
然后来看下配置文件里需要注意的几个地方:
###因为我们每一个站点的日志文件不止一份,所以LogFile必须按照以下模式配置 LogFile="/usr/local/services/awstats-7.4/tools/logresolvemerge.pl /nginx_log/log_analyze/www/*.log* |" ###DirData按照上图所示,存储于result下,例如 result/www result/img等 DirData="/usr/local/services/awstats-7.4/result/www" ###DirCgi="/awstats" 将此行注释掉 LoadPlugin="decodeutfkeys" ###将此行的注释打开。否则页面“搜索关键字”可能乱码 同时yum install perl-String-Escape perl-URI-Encode 安装perl字符及URL解码模块
然后再看“配置文件”的生成管理:
各站点的配置文件存放于awstats/etc下,如www.conf,img.conf等。面对如此多的配置文件,这里写了个简单的小脚本来批量修改/生成配置文件。我们只需修改好一份配置文件,再运行该脚本即可(如,以www.conf为模板, 则执行"sh awstats/shells/batch_conf_file.sh www")
cat awstats/shells/batch_conf_file.sh
#!/bin/sh ###批量建数据目录,批量 创建各域名配置文件 cd /usr/local/services/awstats-7.4 for i in `ls result` #这一步需下文的日志收集脚本执行完,在result目录下生成了各站点目录才能正确执行 do if [ $1 != $i ];then echo -e "\n------ create $i.conf -------" rsync -a etc/$1.conf etc/$i.conf echo -e "------replace $1 by $i -------" sed -i "/^[^#].*/ s/$1/$i/g" etc/$i.conf fi done
最后来看fastcgi模式的配置
1、在tools/nginx/目录下有相关文件
2、将tools/nginx/awstats-fcgi.php 拷贝至wwwroot/cgi-bin/fcgi.php
3、修改tools/nginx/awstats-nginx.conf 文件相关配置,并在nginx主配置文件里面引用该文件
server { listen 80; server_name awstats.abc.com; root /usr/local/services/awstats-7.4/wwwroot; #charset utf8; index index.html; # Static awstats files: HTML files stored in DOCUMENT_ROOT/awstats/ location /awstats/classes/ { alias /usr/local/services/awstats-7.4/wwwroot/classes/; } location /awstats/css/ { alias /usr/local/services/awstats-7.4/wwwroot/css/; } location /awstats/icon/ { alias /usr/local/services/awstats-7.4/wwwroot/icon/; } location /awstats-icon/ { alias /usr/local/services/awstats-7.4/wwwroot/icon/; } location /awstats/js/ { alias /usr/local/services/awstats-7.4/wwwroot/js/; } # Dynamic stats. location ~ ^/cgi-bin/(awredir|awstats)\.pl { gzip off; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME $document_root/cgi-bin/fcgi.php; fastcgi_param X_SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param X_SCRIPT_NAME $fastcgi_script_name; include fastcgi_params; #下面这三行酌情设置。太小可能会导致页面“链接被重置” fastcgi_connect_timeout 300; fastcgi_send_timeout 300; fastcgi_read_timeout 300; } }
三、集中展示页面
如果有多个域名的话,每次查看都需要输入对应的一串url肯定是很麻烦的。这里用html和JavaScript写了一个小页面,把所有域名的入口集中到一起,如下图所示
index.html文件内容如下(如有站点的增减,只需在js的vhost数组对应增减即可)
源站日志分析 源站日志分析平台
四、日志收集、处理
这里我在awstats server上写了一套shell脚本来实现无论web server上运行哪些站点,只要告诉脚本该server的ip即可将该server上所有站点日志拷贝至本机的合适位置以待分析。各server的ip信息记录于"/root/shells/ips.txt",每条记录一行,如“web1-192.168.1.1”
来看脚本内容,脚本内注释应该已经比较详细了
cat awstats/shells/cp_logs_for_awstats.sh
#!/bin/sh log_dir_s=/nginx_log/backup #各台server日志文件源目录 log_dir_d=/nginx_log/log_analyze #定义将日志在本地后的最终存放路径 time1=`date -d "1 day ago" +%F` #获取一天前的日期 time2=`date -d "2 day ago" +%F` basedir=/usr/local/services/awstats-7.4 #awstats目录 echo -e "`date` 开始拉取日志\n" >$basedir/logs/cron.log ###ips.txt记录需要统计日志的所有server的hostname和ip.若增加web server,只需在该文件添加新server的记录如“web1-192.168.1.1”即可 for server_ip in `cat /root/shells/ips.txt`; do ip=`echo $server_ip|awk -F '-' '{print $2}'` #获取各server IP echo -e "\e[1;32m \nrsync logs from $ip\e[0m" >>$basedir/logs/cron.log ###将该ip下的所有前一天的access日志拷贝至本地/tmp下 rsync -avz --compress-level=6 --exclude="default.*" --min-size=1k $ip:$log_dir_s/*access*"$time1" /tmp/ if [ $? != 0 ];then #检查rsync命令执行成功与否 echo -e "\e[1;31m \nrsync logs from $ip seems wrong!\e[0m" >>$basedir/logs/cron.log fi ###取得上一天的日志备份文件名 log_name for log_name in `cd /tmp/;ls *.access.log*`; do vhost_name=`echo $log_name|awk -F.access '{print $1}'` #取得web server的vhost名 echo -e "\e[1;32m ----------处理$vhost_name日志----------\e[0m" ###在本地建立目录分类存放cp过来的日志 if [ ! -d "$log_dir_d/$vhost_name" ];then mkdir $log_dir_d/$vhost_name fi rm -f $log_dir_d/$vhost_name/*"$time2"* ###从tmp下依次mv日志文件到目标目录,以日志所在server的ip为后缀 mv /tmp/$log_name $log_dir_d/$vhost_name/$log_name.$ip ###在swstats目录下建立目录用于存放awstats.pl处理日志生成的“中间文件” if [ ! -d "$basedir/result/$vhost_name" ];then mkdir $basedir/result/$vhost_name fi done done echo -e "`date` 拉取日志完成\n" >>$basedir/logs/cron.log
上面的shell脚本只是将分散在各web server的日志文件按规则拉取到了本地特定目录,接下来的shell脚本用来调用awstats.pl循环处理各站点日志
cat awstats/shells/cron_awstats_update.sh
#!/bin/sh #awstats日志分析 basedir=/usr/local/services/awstats-7.4 cd $basedir #循环更新所有站点日志统计信息 echo -e "\e[1;31m-------`date "+%F %T"` 开始处理---------\n\e[0m" >>logs/cron.log for i in `ls result/` do echo -e "\e[1;32m -----`date "+%F %T"` 处理 $i 日志-----\e[0m" >>logs/cron.log perl wwwroot/cgi-bin/awstats.pl -config=etc/$i.conf -lang=cn -update &>>logs/cron.log done echo -e "\e[1;31m\n-------`date "+%F %T"` 处理完成---------\e[0m" >>logs/cron.log
这两个脚本作为计划任务在awstats server运行,我的crontab如下
#日志分析平台 5 0 * * * /bin/bash /root/shells/cp_logs_to_img2_for_awstats.sh ; /bin/bash /root/shells/cron_awstats_update.sh
至此,这么一套东西就算完成了。
写了这么多,希望我说清楚了。看到此处的伙伴,希望能对你们有些许帮助吧!