• 03 . Nginx日志配置及日志切割


    Nginx日志

    日志对于统计排错来说是非常有利的,Nginx日志主要分为两种: access_log(访问日志)和error_log(错误日志),通过访问日志可以得到用户的IP地址、浏览器的信息,请求的处理时间等信息。错误日志记录了访问出错的信息,可以帮助我们定位错误的原因。

    设置Access_log日志

    访问日志主要记录客户端的请求。客户端向Nginx服务器发起的每一次请求都记录在这里。客户端IP,浏览器信息,referer,请求处理时间,请求URL等都可以在访问日志中得到。当然具体要记录哪些信息,你可以通过log_format指令定义。

    语法
    access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]]; # 设置访问日志
    access_log off; # 关闭访问日志
    
    # path 指定日志的存放位置。
    # format 指定日志的格式。默认使用预定义的combined。
    # buffer 用来指定日志写入时的缓存大小。默认是64k。
    # gzip 日志写入前先进行压缩。压缩率可以指定,从1到9数值越大压缩比越高,同时压缩的速度也越慢。默认是1。
    # flush 设置缓存的有效时间。如果超过flush指定的时间,缓存中的内容将被清空。
    # if 条件判断。如果指定的条件计算为0或空字符串,那么该请求不会写入日志。
    # 另外,还有一个特殊的值off。如果指定了该值,当前作用域下的所有的请求日志都被关闭。
    
    作用域

    可以应用access_log指令的作用域分别有http,server,location,limit_except,也就是说,这几个作用域使用该命令,Nginx会报错

    基本用法

    access_log /usr/local/nginx/logs/b_test/access.log;

    该例子指定日志的写入路径为/usr/local/nginx/logs/b_test/access.log,日志格式使用默认的combined

    log_format指令
    # Nginx预定义了名为combined日志格式,如果没有明确指定日志格式默认使用该格式:
    # 如果想使用自定义格式,可以使用log_format自定义
    
    log_format combined '$remote_addr - $remote_user [$time_local] '
                        '"$request" $status $body_bytes_sent '
                        '"$http_referer" "$http_user_agent"';
    
    # 语法:
    # log_format name [escape=default|json] string ...;
            
    name:               # 表示格式名称,在access_log指令中引用
    string:             # 要定义的日志格式内容,该参数可以有多个,参数中可以使用Nginx变量
    log_format:         # 有默认的无需设置的combined日志格式,相当于apache的combined格式,日志格式如下.
    escape:				# 设置变量中的字符编码方式是json还是default,默认是default
    
    log_format combined '$remote_addr - $remote_user [$time_local] '
                        ' "$request" $status $body_bytes_sent '
                        ' "$http_referer" "$http_user_agent" ';
    
    #如果Nginx位于负载均衡器,squit,nginx反向代理之后,web服务器无法直接获取到客户端真实的IP地址。
    #而此时$remote_addr 获取的是反向代理的IP地址.
    #反向代理服务器在转发请求的http头信息中,可以增加X-Forwarded-For信息,用来记录客户端IP地址和客户端请求的IP服务器地址.日志格式如下:
    
    log_format porxy '$http_x_forwarded_for - $remote_user [$time_local] '
                     ' "$request" $status $body_bytes_sent '
                     ' "$http_referer" "$http_user_agent" ';
    

    下面是log_format指令常用的一些变量

    变量 含义
    $bytes_sent 发送给客户端的总字节数
    $body_bytes_sent 发送给客户端的字节数,不包括响应头的大小
    $connection 连接序列号
    $connection_requests 当前通过连接发出的请求数量
    $msec 日志写入时间,单位为秒,精度是毫秒
    $pipe 如果请求是通过http流水线发送,则其值为"p",否则为“."
    $request_length 请求长度(包括请求行,请求头和请求体)
    $request_time 请求处理时长,单位为秒,精度为毫秒,从读入客户端的第一个字节开始,直到把最后一个字符发送张客户端进行日志写入为止
    $status 响应状态码
    $time_iso8601 标准格式的本地时间,形如“2017-05-24T18:31:27+08:00”
    $time_local 通用日志格式下的本地时间,如"24/May/2017:18:31:27 +0800"
    $http_referer 请求的referer地址。
    $http_user_agent 客户端浏览器信息。
    $remote_addr 客户端IP
    $http_x_forwarded_for 当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置。
    $request 完整的原始请求行,如 "GET / HTTP/1.1"
    $remote_user 客户端用户名称,针对启用了用户认证的请求
    $request_uri 完整的请求地址,如 "https://daojia.com/"

    Nginx日志分析

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '  
     '$status $body_bytes_sent "$http_referer" '  
     '"$http_user_agent" "$http_x_forwarded_for"';  
      
    日志条目:  
    117.107.143.155 - - [01/Nov/2019:16:29:39 +0800] "GET /favicon.ico HTTP/1.1" 404 555   
    "http://39.108.140.0/" "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.17 Safari/537.36" "-"  
    
    # Nov,是Novemenber(11)月的缩写  
    # Feb是February(2)月的缩写  
    

    设置error_log

    错误日志在Nginx中通过error_log指令实现的,该指令记录服务器和请求处理过程中的错误信息

    语法

    配置错误日志文件的路径和日志级别

    error_log file [level];
    Default:    
    error_log logs/error.log error;
    
    # 第一个参数指定日志的写入位置。
    
    # 第二个参数指定日志的级别。level可以是debug, info, notice, warn, error, crit, alert,emerg中的任意值。可以看到其取值范围是按紧急程度从低到高排列的。只有日志的错误级别等于或高于level指定的值才会写入错误日志中。默认值是error。
    
    基本用法

    error_log /var/logs/nginx/nginx-error.log

    # 它可以配置在:main, http, mail, stream, server, location作用域。
    
    # 例子中指定了错误日志的路径为:/var/logs/nginx/nginx-error.log,日志级别使用默认的error。
    

    Open_log_file_cache

    每一条日志记录的写入都是先打开文件再写入记录,然后关闭日志文件。如果你的日志文件路径中使用了变量,如access_log /var/logs/$host/nginx-access.log,为提高性能,可以使用open_log_file_cache指令设置日志文件描述符的缓存。

    语法
    open_log_file_cache max=N [inactive=time] [min_uses=N] [valid=time];
    
    #对于每一条日志记录,都将是先打开文件,再写入日志,然后关闭访问量大的时候IO会变多,会造成速度变慢.
    #此时可以使用open_log_file_cache来设置日志文件缓存(默认是off),先将日志写到内存中,等待时机然后写入硬盘,格式如下
    
    # max: 设置缓存中的最大文件描述符数量,如果缓存被占满,采用LRU(least recently used最近最少使用)算法将描述符关闭
    # inactive: 设置存活时间,默认是10s
    # min_uses: 设置在inactive时间段内,日志文件最少使用多少次后,该日志文件描述符记入缓存中,默认是1次
    # valid: 设置检查频率,默认60s
    # off: 不使用缓存
    
    #open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;
    
    基本用法

    open_log_file_cache max=1000 inactive=20s valid=1m min_uses=2;

    # 它可以配置在http、server、location作用域中。
    
    # 例子中,设置缓存最多缓存1000个日志文件描述符,20s内如果缓存中的日志文件描述符至少被被访问2次,才不会被缓存关闭。每隔1分钟检查缓存中的文件描述符的文件名是否还存在
    

    Nginx日志轮转

    默认nginx不会自动切割日志,当日志文件越来越大时,不再浪费磁盘空间,nginx的性能也会降低。可以使用Linux的logrotate来解决这个问题。

    logrotate可以自动对日志进行切割,压缩和删除。而且自动化处理,不需要人为操作,使用非常方便。

    rpm -ql nginx |grep log
    /etc/logrotate.d/nginx
    /var/log/nginx
    #轮转规则文件
    vim /etc/logrotate.d/nginx
    /var/log/nginx/*.log {
    daily
    missingok
    rotate 52
    compress
    delaycompress
    notifempty
    create 640 nginx adm
    sharedscripts
    postrotate
    if [ -f /var/run/nginx.pid ]; then
    kill -USR1 `cat /var/run/nginx.pid`
    fi
    endscript
    }
    #-USR1:发送1信号
    
    # 手动运行脚本分割日志
    sudo /usr/sbin/logrotate -f /etc/logrotate.d/nginx
    
    logrotate参数说明
    # 配置		   # 说明
    daily			# 指定转储周期为每天
    weekly			# 指定转储周期为每周
    monthly			# 指定转储周期为每月
    rotate count	# 指定日志文件删除之前转储的次数,0 指没有备份,5 指保留5 个备份
    compress		# 通过gzip 压缩转储以后的日志
    nocompress		# 不做gzip压缩处理
    create mode owner group	# 轮转时指定创建新文件的属性,如create 0777 nobody nobody
    nocreate		# 不建立新的日志文件
    delaycompress	# 和compress 一起使用时,转储的日志文件到下一次转储时才压缩
    nodelaycompress	# 覆盖 delaycompress 选项,转储同时压缩
    missingok		# 如果日志丢失,不报错继续滚动下一个日志
    ifempty			# 即使日志文件为空文件也做轮转,这个是logrotate的缺省选项
    notifempty		# 当日志文件为空时,不进行轮转
    mail address	# 把转储的日志文件发送到指定的E-mail 地址
    olddir directory # 转储后的日志文件放入指定的目录,必须和当前日志文件在同一个文件系统
    noolddir		# 转储后的日志文件和当前日志文件放在同一个目录下
    sharedscripts	# 运行postrotate脚本,作用是在所有日志都轮转后统一执行一次脚本。如果没有配置这个,那么每个日志轮转后都会执行一次脚本
    prerotate		# 在logrotate转储之前需要执行的指令,例如修改文件的属性等动作;必须独立成行
    postrotate		# 在logrotate转储之后需要执行的指令,例如重新启动 (kill -HUP) 某个服务!必须独立成行
    dateext			# 使用当期日期作为命名格式
    dateformat .%s	# 配合dateext使用,紧跟在下一行出现,定义文件切割后的文件名,必须配合dateext使用,只支持 %Y %m %d %s 这四个参数
    size(minsize) log-size	# 当日志文件到达指定的大小时才转储,log-size能指定bytes(缺省)及KB (sizek)或MB(sizem),例如 size 100M
    
    添加定时任务
    sudo crontab -u root -e
    # rotate nginx log erery day
    0 0 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx
    
    # 如果要删除上面定时任务,运行如下命令
    contab -r
    
    # 如果任务没有正确执行,可以通过如下命令查看任务日志
    vim /var/log/cron
    
    # 也可以通过自己写脚本日志分割
    #!/bin/bash
    base_path='/usr/local/nginx/logs'               # 保存日志的目录
    log_path=$(date -d yesterday +"%Y%m")           
    day=$(date -d yesterday +"%d")                  # 日期作为日志的标识
    mkdir -p $base_path/$log_path                   # 根据年月管理日志
    mv $base_path/access.log $base_path/$log_path/access_$day.log
    #echo $base_path/$log_path/access_$day.log
    kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`# 信号通知nginx重新开始记录日志
    
    # Crontab执行任务
    30 02 * * * /cron/nginx/log.sh //每天2时30分(建议在02-04点之间,系统负载小)
    

    常见的日志分析命令案例

    # 1.统计2019年11月1号的pv量
    grep '01/Nov/2019' /var/log/nginx/access.log |wc -l
    102
    
    # 2.统计2019年11月1号访问最多的10个IP
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{ips[$1]++ } END{for (i in ips){print i,ips[i]}}' |sort -k2 -rn |head -n 10
    49.233.69.195 201
    190.94.151.52 1
    117.107.143.155 1
    
    # 3.统计2019年11月1号访问大于100次的IP
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{ips[$1]++ } END{for(i in ips){if (ips[i]>100) {print i,ips[i]}}}'
    49.233.69.195 201
    
    # 4.统计2019年11月1号访问最多的10个页面
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{urls[$7]++ } END{for(i in urls){print urls[i],i}}'|sort -k1 -rn  |head -n 10
    202 /
    1 /zhou.html
    1 /favicon.ico
    
    # 5.统计2019年11月1号每个URL访问内容的总大小($body_bytes_sent)
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{urls[$7]++; size[$7]+=$10} END{for (i in urls){print urls[i],size[i],i}}' |sort -k1 -rn |head -n10
    202 123624 /
    1555 /favicon.ico
    14 /zhou.html
    
    
    # 6.统计2019年11月1号每个IP访问状态码数量($status)
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{ip_code[$1" "$9]++} END{for (i in ip_code){print i,ip_code[i]}}' |sort -k1 -rn |head -n 10
    190.94.151.52 200 1
    117.107.143.155 404 1
    49.233.69.195 200 202
    
    # 7.统计2019年11月1号 IP访问状态码为404及出现次数($status)    # 此方法有点问题,不是很正确,后期再完善
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{if ($9="404"){ip_code[$1" "$9]++}} END{for(i in ip_code){print i,ip_code[i]}}'
    117.107.143.155 404 1
    190.94.151.52 404 1
    49.233.69.195 404 202
    
    # 8.统计前一分钟的pv量
    date1=$(date -d '1 minute ago' +%d/%b/%Y:%H:%M); awk -v date=$date1 '$0 ~ date {i++} END{print i}' /var/log/nginx/access.log
    100
    
    # 9.统计两个时间点之间的访问状态码404分别是多少个
    awk '$4>="[01/Nov/2019:16:29:38" && $4<="[01/Nov/2019:17:38:36" {if($9="404"){ip_code[$1" "$9]++}} END{for (i in ip_code){print i,ip_code[i]}}' /var/log/nginx/access.log    # 
    117.107.143.155 404 1
    190.94.151.52 404 1
    47.92.24.137 404 1
    80.82.70.187 404 1
    49.233.69.195 404 404
    
    # 10.统计2019年11月1号各种状态码数量
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{code[$9]++} END{for(i in code){print i,code[i]}}'
    200 405
    404 3
    
    grep '01/Nov/2019' /var/log/nginx/access.log |awk '{code[$9]++;total++} END{for(i in code) {printf i" "; printf code[i]"	";printf "%.2f",code[i]/total*100;print "%"}}'
    200 405    99.26%
    404 3    0.74%
    
    # Nginx日志字段
    $remote_addr        $1            # 远程客户端IP
    $time_local         $4            # 访问时间
    $request            $7            # HTTP请求(方法,http版本,URL地址)
    $status             $9            # HTTP状态码
    $body_bytes_sent    $10           # 发送给客户端的字节数,不包括响应头的大小,首页多大就是多大
    
  • 相关阅读:
    Vue学习之监听methods、watch及computed比较小结(十一)
    Vue学习之路由vue-router传参及嵌套小结(十)
    Vue学习之路由vue-router小结(九)
    Vue学习之组件切换及父子组件小结(八)
    Vue学习之全局和私有组件小结(七)
    Vue学习之动画小结(六)
    Vue学习之vue-resource小结(五)
    Vue学习之生命周期钩子小结(四)
    Vue学习之过滤器和自定义指令小结(三)
    Vue学习之品牌案例部分代码小结(二)
  • 原文地址:https://www.cnblogs.com/you-men/p/12827117.html
Copyright © 2020-2023  润新知