通过shell和redis来实现集群业务中日志的实时收集分析_第1张图片

在统计项目中,最难实施的就是日志数据的收集。日志分布在全国各个机房,而且数据量比较大,像rsync+inotify这种方式显然不能满足快速日志同步的要求。 当然大家也可以用fluentd和flume采集日志数据,除了这个我们也可以自己写一套简单的。

 

我写的这个日志分析系统 流程是:

   
   
   
   
  1. 1   在客户端收集数据,然后通过redis pub方式把数据发给服务端 
  2.  
  3. 2   服务器端是redis的sub    他会把数据统一存放在一个文件,或者当前就过滤出来 

 

客户端收集日志的更新数据

   
   
   
   
  1. #!/bin/bash 
  2.  
  3. DATE=`date +%s` 
  4. LOGFILE=$1 
  5. if [ ! -f $1 ];then 
  6.  echo "LOG file did not give or it's not a file" 
  7. fi 
  8. sleep_time="2" 
  9.  
  10. count_init=`wc -l ${LOGFILE}|awk '{print $1}'
  11. while true 
  12. do 
  13. DATE_NEW=`date +%s` 
  14. #    DATE=$(date +%s) 
  15.     count_new=`wc -l ${LOGFILE}|awk '{print $1}'
  16.     add_count=$((${count_new} - ${count_init})) 
  17.     count_init=${count_new} 
  18.         if [ ! -n "${add_count}" ] 
  19.         then 
  20.             add_count=0 
  21.         fi 
  22.      QPS=$((${add_count}/${sleep_time})) 
  23.      info=`tail -n ${add_count} ${LOGFILE}`     
  24.      echo $info      
  25. #    我们可以把info这个值传出去 
  26.      echo " Then QPS at `date -d "1970-01-01 UTC ${DATE_NEW} seconds" +"%Y-%m-%d %H:%M:%S"` is "${QPS} 
  27. #    echo " DATE_NEW: " $DATE_NEW " DATE_PLUS :" $DATE_PLUS 
  28. sleep $sleep_time 
  29. done 

 

通过shell和redis来实现集群业务中日志的实时收集分析_第2张图片

把实时的日志也打印出来

通过shell和redis来实现集群业务中日志的实时收集分析_第3张图片

 

想传到服务端,我们只需要在脚本里面加下面这命令就ok了~ 

/root/redis-bash-cli -h 10.10.10.61 PUBLISH rui "$info"

 

redis-bash-cli  这个是客户端的脚本,可以把数据publish过去

   
   
   
   
  1. #!/bin/bash   
  2. source /usr/share/redis-bash/redis-bash-lib 2> /dev/null  
  3. if [ $? -ne 0 ]; then  
  4.   LIBFOLDER=${0%/${0##*/}}  
  5.   source ${LIBFOLDER}/redis-bash-lib 2> /dev/null  
  6.   if [ $? -ne 0 ]; then  
  7.     echo "can't find redis-bash-lib in /usr/share/redis-bash or ${LIBFOLDER}"  
  8.     exit 127   
  9.   fi  
  10. fi  
  11. REDISHOST=localhost  
  12. REDISPORT=6379  
  13. REPEAT=1  
  14. DELAY=0  
  15. while getopts ":h:n:p:r:a:i:" opt  
  16. do  
  17.     case ${opt} in  
  18.         h) REDISHOST=${OPTARG};;  
  19.         n) REDISDB=${OPTARG};;  
  20.         p) REDISPORT=${OPTARG};;  
  21.         r) REPEAT=${OPTARG};;  
  22.         a) AUTH=${OPTARG};;  
  23.         i) DELAY=${OPTARG};;  
  24.     esac  
  25. done  
  26. shift $((${OPTIND} - 1))  
  27. if [ "${REDISHOST}" != "" ] && [ "${REDISPORT}" != "" ]  
  28. then  
  29.     exec 6<>/dev/tcp/${REDISHOST}/${REDISPORT} # open fd  
  30.     if [ $? -ne 0 ]; then  
  31.         exit 1  
  32.     fi  
  33. else  
  34.     echo "Wrong arguments"  
  35.     exit 255  
  36. fi  
  37. [ "${AUTH}" != "" ] && redis-client 6 AUTH ${AUTH} > /dev/null  
  38. [ "${REDISDB}" != "" ] && redis-client 6 SELECT ${REDISDB} > /dev/null  
  39. for ((z=1;z<=${REPEAT};z++))  
  40. do  
  41.     redis-client 6 "${@}"  
  42.     if [ $? -ne 0 ]; then  
  43.         exit 1  
  44.     fi  
  45.     [ ${DELAY} -gt 0 ] && sleep ${DELAY}  
  46. done  
  47. exec 6>&- #close fd  

 

日志服务端

通过shell和redis来实现集群业务中日志的实时收集分析_第4张图片

 

redis-publish-test  这个是日志服务端,可以收到publish的数据

 

   
   
   
   
  1. #!/bin/bash   
  2. source /usr/share/redis-bash/redis-bash-lib 2> /dev/null  
  3. if [ $? -ne 0 ]; then  
  4.   LIBFOLDER=${0%/${0##*/}}  
  5.   echo $LIBFOLDER  
  6.   source ${LIBFOLDER}/redis-bash-lib 2> /dev/null  
  7.   if [ $? -ne 0 ]; then  
  8.     echo "can't find redis-bash-lib in /usr/share/redis-bash or ${LIBFOLDER}"  
  9.     exit 127   
  10.   fi  
  11. fi  
  12. REDISHOST=localhost  
  13. REDISPORT=6379  
  14. while getopts ":h:p:" opt  
  15. do  
  16.     case ${opt} in  
  17.         h) REDISHOST=${OPTARG};;  
  18.         p) REDISPORT=${OPTARG};;  
  19.     esac  
  20. done  
  21. shift $((${OPTIND} - 1))  
  22. while true  
  23. do  
  24.     exec 5>&-  
  25.     if [ "${REDISHOST}" != "" ] && [ "${REDISPORT}" != "" ]  
  26.     then  
  27.         exec 5<>/dev/tcp/${REDISHOST}/${REDISPORT} # open fd  
  28.     else  
  29.         echo "Wrong arguments"  
  30.         exit 255  
  31.     fi  
  32.     redis-client 5 SUBSCRIBE ${1} > /dev/null # subscribe to the pubsub channel in fd 5  
  33.     while true  
  34.     do  
  35.         unset ARGV  
  36.         OFS=${IFS};IFS=$'\n' # split the return correctly  
  37.         ARGV=($(redis-client 5))  
  38.         IFS=${OFS}  
  39.         if [ "${ARGV[0]}" = "message" ] && [ "${ARGV[1]}" = "${1}" ]  
  40.         then  
  41.         echo ${ARGV[2]}  
  42.         a=${ARGV[2]}  
  43.             echo $($a)  
  44.             echo "Message from pubsub channel: ${ARGV[2]}"  
  45.         elif [ -z ${ARGV} ]  
  46.         then  
  47.             sleep 1  
  48.             break  
  49.         fi  
  50.     done  
  51. done