介绍怎样用scribe收集各台服务器上nginx和php程序运行时自身产生的日志(error.log、access_log等),实现的方法很简单——用logrotate切日志,将读取的日志通过scribe_cat送给中心的日志服务器。而正常业务产生的日志由开发自己编写代码直接送给scribe不在讨论的范畴,收集nginx和php程序产生日志的方法也可以发散到其它程序日志的收集如mysql。

1、scribe_cat脚本
scribe_cat是scribe源码包提供的一个python脚本,用来将标准输入的信息送给scribe服务器,在源码包的examples目录下。可以简单测试一下:

#-h参数用来指定scribe服务器的ip和端口
#1_test是日志类别表示,跟scribe配置相关,是必要的参数
[root@TestHost ~] echo "hello world" | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 1_test

这条命令执行后,如果scribe配置中有1_test相关的store那么就会在相关目录下生成一个文件且文件的内容有一行信息是”hello workd”
用echo、sed、awk等作为scribe_cat的标准输入最后都会带上一个换行符”\n”,这样就带来一个困扰就是会发现scribe收集的日志会有很多空行。解决空行的方法就是将标准输入信息最后一行的换行符去掉,编辑scribe_cat脚本:

#导入新的模块用于正则匹配
from re import sub
#新增的语句,用来接收标准输入的信息
sendMessage = sys.stdin.read()
#修改的语句,将标准输入信息最后一个换行符删除
log_entry = scribe.LogEntry(category = category, message = sub(r "\n$" , '', sendMessage))

2、编写收集日志脚本pushscribe.sh
脚本功能:
每天23点59分对nginx和php的日志切割一次(切割目的主要是减轻每次读取日志的压力),每分钟累计采集数次nginx、php日志内容并将读取的内容由scribe_cat送给中心的scribe达到收集日志的功能,每条日志文件在server落地的时候加上对应主机的主机名用来标识日志的来源。
脚本的内容如下,其实nginx和php的日志可以写成一个迭代,为了简介清晰还是分开写的好。

#!/bin/bash
npath= '/var/log/nginx/'
ppath= '/var/log/php-fpm/'
countfile= '.count'
host=` hostname `
date =` date + '-%Y%m%d' `
dflag=` date + '%H%M' `
 
#每分钟读取日志的次数,一天的最后一分钟只读取一次
if [[ $dflag == '2359' ]]; then
     count=1
else
     count=2
fi
for ((i=0; i<$count; i++))
{
#nginx
cd $npath
if [[ $dflag == '2359' ]]; then
     /usr/sbin/logrotate /etc/logrotate_hd .conf    #每天23:59切割日志
     for fname in ` ls | grep -E ".com$|.log$" `
     do
         startnum=` grep "^$fname" $countfile | awk '{print $2}' `
         if [ -e $fname$ date ]; then
             sed -i "s/^$fname $startnum/$fname 1/" $countfile
             endnum=` awk 'END{print NR}' $fname$ date `
             awk - v h= " $host" "{if((NR>=$startnum)&&(NR<=$endnum))print \$0 h}" $fname$ date | /usr/local/scribe/examples/scribe_cat -h 127.0.0.1:2463 "10_$fname"
         else
             endnum=` awk 'END{print NR}' $fname`
             if [ $endnum -gt $startnum ]; then
                 sed -i "s/^$fname $startnum/$fname $endnum/" $countfile
                 awk - v h= " $host" "{if((NR>=$startnum)&&(NR<$endnum))print \$0 h}" $fname | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 "10_$fname"
             fi
         fi
     done
else
     for fname in ` ls | grep -E ".com$|.log$" `
     do
         startnum=` grep "^$fname" $countfile | awk '{print $2}' `
         if [[ -z $startnum ]]; then
             echo "$fname 1" >> $countfile
             startnum=1
         fi
         endnum=` awk 'END{print NR}' $fname`
         if [ $endnum -gt $startnum ]; then
             sed -i "s/^$fname $startnum/$fname $endnum/" $countfile
             awk - v h= " $host" "{if((NR>=$startnum)&&(NR<$endnum))print \$0 h}" $fname | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 "10_$fname"
         fi
     done
fi
 
#php-fpm
cd $ppath
if [[ $dflag == '2359' ]]; then
     for fname in ` ls | grep -E ".slow$|.log$" `
     do
         startnum=` grep "^$fname" $countfile | awk '{print $2}' `
         if [ -e $fname$ date ]; then
             sed -i "s/^$fname $startnum/$fname 1/" $countfile
             endnum=` awk 'END{print NR}' $fname$ date `
             awk - v h= " $host" "{if((NR>=$startnum)&&(NR<=$endnum))print \$0 h}" $fname$ date | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 "11_$fname"
         else
             endnum=` awk 'END{print NR}' $fname`
             if [ $endnum -gt $startnum ]; then
                 sed -i "s/^$fname $startnum/$fname $endnum/" $countfile
                 awk - v h= " $host" "{if((NR>=$startnum)&&(NR<$endnum))print \$0 h}" $fname | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 "11_$fname"
             fi
         fi
     done
else
     for fname in ` ls | grep -E ".slow$|.log$" `
     do
         startnum=` grep "^$fname" $countfile | awk '{print $2}' `
         if [[ -z $startnum ]]; then
             echo "$fname 1" >> $countfile
             startnum=1
         fi
         endnum=` awk 'END{print NR}' $fname`
         if [ $endnum -gt $startnum ]; then
             sed -i "s/^$fname $startnum/$fname $endnum/" $countfile
             awk - v h= " $host" "{if((NR>=$startnum)&&(NR<$endnum))print \$0 h}" $fname | /usr/local/scribe/examples/scribe_cat -h 192.168.186.135:2463 "11_$fname"
         fi
     done
fi
sleep 10
}

3、添加定时任务

* * * * * root sh /tool/pushscribe .sh > /dev/null 2>&1

关于怎样切割php和nginx的日志在《日志管理(2) 用logrotate切割php和nginx日志》中已经介绍了,不过要注意的是已经在脚本中对日志进行切割后,就不要再将切割日志的动作放到定时任务里,避免重复切割造成不必要的麻烦。
文章出处:http://www.xiaomastack.com/2014/11/11/scribe-nginx-php/