zoukankan      html  css  js  c++  java
  • nginx日志的监控【转】

    第一:nginx的基础监控:

    1.进程监控

    2.端口监控

    在这里nginx的基础监控就不详细说了,注意的是:这两个是必须要加的。并且对于zabbix而言的话,一定要加上触发器的。有问题必须报警。

    第二:nginx的特殊监控:

    1.利用nginx的stub_status模块监控:

        location /ngn_status
        {
            stub_status on;
            access_log off;
        }

    (1)nginx的每分钟的总请求数

    curl -s http://127.0.0.1/ngn_status| grep connection | awk -F ":" '{print $2}'

    (2)nginx的活跃数的链接数

    accepts_handled=`curl -s http://127.0.0.1/ngn_status| awk '$1~/^s/ {for (i=1;i<=2;i++) {print;getline}}' |awk '{print $1,$2,$3}' | grep -v server`
    accepts=`echo $accepts_handled | awk '{print $1}'`
    handled=`echo $accepts_handled | awk '{print $2}'`
    echo `expr $accepts - $handled`

    (3)nginx的丢弃数连接数

    #每分钟的总请求数,zabbix上需要配置减法哦!!
    all_requests=`curl -s http://127.0.0.1/ngn_status| awk '$1~/^s/ {for (i=1;i<=2;i++) {print;getline}}' |awk '{print $1,$2,$3}' | grep -v server | awk '{print $3}'`
    echo $all_requests

    2.日志监控

    (1):nginx的日志监控前提:

    i.规范nginx的格式,规范日志格式。这是很多团队容易忽略的地方,有时候多一个空格会让日志分析的复杂度大为增加。

    nginx的日志格式:

    log_format  main   '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent $request_time $upstream_response_time $upstream_addr "$http_referer" "$http_user_agent" "$http_x_forwarded_for"';

    详解:                          $remote_addr 记录客户端的ip地址,如有代理会记录代理的ip地址   

    复制代码
                              $remote_user                      记录客户端用户名称                     
                              [$time_local]                     来访时间                                                                                                                                                                                  
                              "$request"                        记录请求的url与http协议 
                              $status                           记录请求状态                                                                                                                                                        
                              $body_bytes_sent                  记录发送给客户端文件主题的大小, 这一个可以用于监控某个文件,图片占用多大的带宽
                              $request_time                     整个请求的总时间
                              $upstream_response_time           请求过程中upstream响应的时间
                              $upstream_addr                    真正提供服务的ip地址
                              "$http_referer"                   用来记录从那个页面链接访问过来的
                              "$http_user_agent"                记录客户端浏览器的相关信息
                              "$http_x_forwarded_for"';         记录客户端访问的真实ip地址
    这里特别解释一下 :remote_addr与http_x_forwarded_for

    remote_addr代表客户端的IP,但它的值不是由客户端提供的,而是服务端根据客户端的ip指定的,当你的浏览器访问某个网站时,假设中间没有任何代理,那么网站的web服务器(Nginx,Apache等)就会把remote_addr设为你的机器IP,如果你用了某个代理,那么你的浏览器会先访问
    这个代理,然后再由这个代理转发到网站,这样web服务器就会把remote_addr设为这台代理机器的IP。正如上面所述,当你使用了代理时,web服务器就不知道你的真实IP了,为了避免这个情况,代理服务器通常会增加一个叫做x_forwarded_for的头信息,把连接它的客户端IP(即你的
    上网机器IP)加到这个头信息里,这样就能保证网站的web服务器能获取到真实IP
    复制代码

    ii.nginx做日志切割,如果nginx没有做日志切割的话,会很大,造成监控误报的情况

    nginx的日志切割有很多种方式方法,例如:利用系统自带的logrotate切割nginx日志,按天shell+crontab来切。

    我用的是shell+crontab,

    脚本:

    复制代码
    #!/bin/bash
    #nginx日志切割脚本
    
    #设置备份日志文件存放目录
    before_log="/var/log/nginx/before_log/"
    
    #生成日志文件存放目录
    log_path="/var/log/nginx/"
    #设置pid文件
    nginx_pid_path="/run/nginx.pid"
    
    #定义日期
    yesterday=`date -d "yesterday" +"%Y%m%d"`
    mkdir -p ${before_log}${yesterday} 
    
    #重命名访问日志文件
    mv ${log_path}access.log ${before_log}${yesterday}/access_admin.log
    
    #重命名错误日志文件
    mv ${log_path}error.log ${before_log}${yesterday}/error_admin.log
    
    #向nginx主进程发信号重新打开日志
    kill -USR1 `cat ${nginx_pid_path}`
    复制代码

    结合crontab每天的0点0分执行该脚本:

    00 00 * * * root /bin/bash /opt/script/cut_nginx_log.sh

    (2)nginx的日志监控:

    i.nginx平均每秒处理的请求数

    cat main.log | awk '{sec=substr($4,2,20);reqs++;reqsBySec[sec]++;} END{print reqs/length(reqsBySec)}'

    ii.nginx的请求在哪一个时间是峰值,以级峰值大小(这个如果日志分析中有的话,就不需要加监控了)

    cat main.log | awk '{sec=substr($4,2,20);requests[sec]++;} END{for(s in requests){printf("%s %s
    ", requests[s],s)}}' | sort -nr | head -n 10

    iii.nginx处理请求的时间

    每分钟nginx处理请求的平均时间,zabbix每分钟检测一次 

    复制代码
    DATE=/bin/date
    one_minute_ago=`$DATE -d "1 minute ago" | awk '{print $4}' | awk '{sub(/...$/,"")}1'`
    all_times=`cat $log | grep $one_minute_ago | awk -F '"' '{print $13}' | awk '{print $1}'`
    all_number=`cat $log | grep $one_minute_ago | awk -F '"' '{print $13}' | awk '{print $1}' | wc -l`sum=0
    for i in `echo $all_times`
    do
        sum=$(echo "$sum + $i" | bc)
    done
    ding=0.0
    if [ $(echo "$sum == $ding"|bc) -eq 1 ];then
        echo "sum" 
    else
        every_num=`gawk -v x=$sum -v y=$all_number 'BEGIN{printf x/y}'`
        echo $every_num 
    fi
    复制代码

    iv.nginx的请求去访问哪里了??

    less main.log | grep 15:59 | awk '{upServer=$13;upTime=$12;if(upServer == "-"){upServer="Nginx"};if(upTime == "-"){upTime=0};upTimes[upServer]+=upTime;count[upServer]++;totalCount++;} END{for(server in upTimes){printf("%s %s%s %ss %s
    ", count[server], count[server]/totalCount *100, "%", upTimes[server]/count[server], server)}}'

    v.nginx的日志中是否有被爬虫的痕迹

    cat main.log | egrep 'spider|bot' | awk '{name=$17;if(index($15,"spider")>0){name=$15};spiders[name]++} END{for(name in spiders) {printf("%s %s
    ",spiders[name], name)}}' | sort -nr

    vi.nginx中出现次数最多的真实ip次数(可以根据实际情况,将xx分钟的大于xx的次数的ip地址找出来)

    awk '{print $NF}' main.log | sort -n |uniq -c | sort -nr 

    vii.nginx中日志的图片占用的带宽大小,以及图片被xx分钟被访问的次数超过xx次进行报警(根据情况扩展)

    cat main.log |awk '{url=$7; requests[url]++;bytes[url]+=$10} END{for(url in requests){printf("%sKB/req %s %s
    ", bytes[url] /requests[url] / 1024, requests[url], url)}}' | sort -nr

    viii.nginx的日志中出现4xx,5xx监控(同样可扩展)(注意:4xx,5xx同时可用这个,写监控脚本的时候用传参的方式哦)

    cat main.log | awk '{print $9}' | grep 4[0-9][0-9] | wc -l
     总结:下面是监控脚本,脚本中图片带宽,访问ip次数没有再脚本中显示,在日志分析中后续会更新...(注:该脚本仅供在zabbix直接使用,nagios还需要在脚本里定义报警级别与阀值)
    复制代码
      1 #!/bin/bash
      2 export PATH=/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin
      3 PROGNAME=`basename $0`
      4 REVISION="2.0"
      5 
      6 
      7 print_usage() {
      8     echo "Usage:"
      9     echo "      $PROGNAME -a act_conn" 
     10     echo "      $PROGNAME -d discard" 
     11     echo "      $PROGNAME -r all_request" 
     12     echo "      $PROGNAME -t time_request -l log" 
     13     echo "      $PROGNAME -s request_reqs -l log" 
     14     echo "      $PROGNAME -c check_spi -l log" 
     15     echo "      $PROGNAME -all get_all -l log" 
     16     echo "      $PROGNAME -g get_count -l log -p port" 
     17     echo "      $PROGNAME -f fail_return -l log -n number" 
     18     echo "      $PROGNAME --help|-h"
     19     echo "      $PROGNAME --version|-v"
     20 }
     21 
     22 
     23 if [ $# -lt 1 ]; then
     24     print_usage
     25     exit $STATE_UNKNOWN
     26 fi
     27 
     28 # Grab the command line arguments
     29 while test -n "$1"; do
     30     case "$1" in
     31         --help)
     32             print_usage
     33             exit $STATE_UNKNOWN
     34             ;;
     35         -h)
     36             print_usage
     37             exit $STATE_UNKNOWN
     38             ;;
     39         --version)
     40             echo "$PROGNAME $REVISION"
     41             exit $STATE_UNKNOWN
     42             ;;
     43         -V)
     44             echo "$PROGNAME $REVISION"
     45             exit $STATE_UNKNOWN
     46             ;;
     47     -a)
     48             act_conn=$2
     49             shift
     50             ;;
     51     -H)
     52             host=$2
     53             shift
     54             ;;
     55     -d)
     56             discard=$2
     57             shift
     58             ;;
     59     -r)
     60             all_request=$2
     61             shift
     62             ;;
     63         -t)
     64             time_request=$2
     65             shift
     66             ;;
     67         -l)
     68             log=$2
     69             shift
     70             ;;
     71         -f)
     72             fail_return=$2
     73             shift
     74             ;;
     75         -n)
     76             number=$2
     77             shift
     78             ;;
     79         -s)
     80             request_reqs=$2
     81             shift
     82             ;;
     83         -c)
     84             check_spi=$2
     85             shift
     86             ;;
     87         -all)
     88             get_all=$2
     89             shift
     90             ;;
     91         -g)
     92             get_count=$2
     93             shift
     94             ;;
     95         -p)
     96             port=$2
     97             shift
     98             ;;
     99     *)
    100             echo "Unknown argument: $1"
    101             print_usage
    102             exit $STATE_UNKNOWN
    103             ;;
    104     esac
    105     shift
    106 done
    107 #获取前一分钟的标志
    108 get_last_minute()
    109 {
    110 DATE=/bin/date
    111 time=`$DATE -d last-minute +%d/%m/%Y:%H:%M | awk -F "/" '{print $1,$3}'`
    112 echo $time
    113 }
    114 
    115 #每分钟活跃的连接数
    116 act_conn()
    117 {
    118 active_connection=`curl -s http://127.0.0.1/ngx_status| grep connection | awk -F ":" '{print $2}'`
    119 echo $active_connection
    120 }
    121 $act_conn
    122 
    123 #是否有丢弃的连接数,为0是一个也没有丢弃
    124 discard()
    125 {
    126 accepts_handled=`curl -s http://127.0.0.1/ngx_status| awk '$1~/^s/ {for (i=1;i<=2;i++) {print;getline}}' |awk '{print $1,$2,$3}' | grep -v server`
    127 accepts=`echo $accepts_handled | awk '{print $1}'`
    128 handled=`echo $accepts_handled | awk '{print $2}'`
    129 echo `expr $accepts - $handled`
    130 }
    131 $discard
    132 
    133 #每分钟的总请求数,zabbix上需要配置减法哦!!
    134 all_request()
    135 {
    136 all_requests=`curl -s http://127.0.0.1/ngx_status| awk '$1~/^s/ {for (i=1;i<=2;i++) {print;getline}}' |awk '{print $1,$2,$3}' | grep -v server | awk '{print $3}'`
    137 echo $all_requests
    138 }
    139 $all_request
    140 
    141 #处理请求的时间
    142 time_request()
    143 {
    144 result=`get_last_minute`
    145 day=`echo $result | awk '{print $1}'`
    146 hour=`echo $result | awk '{print $2}'`
    147 all_times=`cat $log | grep $day | grep $hour | awk '{print $11}'`
    148 all_number=`cat $log | grep $day | grep $hour | awk '{print $11}'| wc -l`
    149 sum=0
    150 for i in `echo $all_times`
    151 do
    152     sum=$(echo "$sum + $i" | bc)
    153 done
    154 if [ $sum == 0 ];then
    155     echo $sum
    156 else
    157     every_num=`gawk -v x=$sum -v y=$all_number 'BEGIN{printf x/y}'`
    158     echo $every_num
    159 fi
    160 }
    161 $time_request
    162 
    163 #日志文件中出现4xx,5xx的错误
    164 fail_return()
    165 {
    166 result=`get_last_minute`
    167 day=`echo $result | awk '{print $1}'`
    168 hour=`echo $result | awk '{print $2}'`
    169 fail_code=`cat $log | grep $day | grep $hour | awk '{print $9}' | grep "$number[0-9][0-9]" | wc -l`
    170 echo $fail_code
    171 }
    172 $fail_return
    173 
    174 #平均每秒的请求数
    175 request_reqs()
    176 {
    177 result=`get_last_minute`
    178 day=`echo $result | awk '{print $1}'`
    179 hour=`echo $result | awk '{print $2}'`
    180 req_num=`cat $log | grep $day |grep $hour | awk '{sec=substr($4,2,20);reqs++;reqsBySec[sec]++;} END{print reqs/length(reqsBySec)}'`
    181 echo $req_num
    182 }
    183 $request_reqs
    184 
    185 #监控是否被爬虫了,zabbix配置触发器的时候只要不等于0就报警
    186 check_spi()
    187 {
    188 result=`get_last_minute`
    189 day=`echo $result | awk '{print $1}'`
    190 hour=`echo $result | awk '{print $2}'`
    191 spi=`cat $log |grep $day |grep $hour | egrep 'spider|bot' |awk '{name=$17;if(index($15,"spider")>0){name=$15};spiders[name]++} END{for(name in spiders) {printf("%s %s
    ",spiders[name], name)}}' | wc -l`
    192 echo $spi
    193 }
    194 $check_spi
    195 
    196 #每分钟用户的访问到了那里?
    197 get_count()
    198 {
    199 result=`get_last_minute`
    200 day=`echo $result | awk '{print $1}'`
    201 hour=`echo $result | awk '{print $2}'`
    202 Arrive=`cat $log | grep $day | grep $hour | awk '{upServer=$13;upTime=$12;if(upServer == "-"){upServer="Nginx"};if(upTime == "-"){upTime=0};upTimes[upServer]+=upTime;count[upServer]++;totalCount++;} END{for(server in upTimes){printf("%s %s
    ",server, count[server])}}'| grep $port`
    203 echo $Arrive | awk '{print $2}'
    204 }
    205 $get_count
    206 
    207 #每分钟的用户访问总数
    208 get_all()
    209 {
    210 result=`get_last_minute`
    211 day=`echo $result | awk '{print $1}'`
    212 hour=`echo $result | awk '{print $2}'`
    213 Arrive=`cat $log | grep $day | grep $hour | awk '{upServer=$13;upTime=$12;if(upServer == "-"){upServer="Nginx"};if(upTime == "-"){upTime=0};upTimes[upServer]+=upTime;count[upServer]++;totalCount++;} END{for(server in upTimes){print totalCount}}'`
    214 echo $Arrive  |awk '{print $1}'
    215 }
    216 $get_all
    复制代码

    转自

    nginx监控 - 迎领启航 - 博客园 https://www.cnblogs.com/ylqh/p/5885465.html

    Nginx 日志中的金矿 https://www.toutiao.com/a6640001649387504135/?tt_from=mobile_qq&utm_campaign=client_share&timestamp=1546050181&app=news_article&utm_source=mobile_qq&iid=26112390770&utm_medium=toutiao_ios&group_id=6640001649387504135

  • 相关阅读:
    java中的 equals 与 ==
    String类的内存分配
    SVN用命令行更换本地副本IP地址
    npoi 设置单元格格式
    net core 微服务框架 Viper 调用链路追踪
    打不死的小强 .net core 微服务 快速开发框架 Viper 限流
    net core 微服务 快速开发框架 Viper 初体验20201017
    Anno 框架 增加缓存、限流策略、事件总线、支持 thrift grpc 作为底层传输
    net core 微服务 快速开发框架
    Viper 微服务框架 编写一个hello world 插件02
  • 原文地址:https://www.cnblogs.com/paul8339/p/10233247.html
Copyright © 2011-2022 走看看