美文网首页优化及排查
nginx配置自定义变量实现日志动态分发

nginx配置自定义变量实现日志动态分发

作者: 寇寇寇先森 | 来源:发表于2018-11-09 15:29 被阅读106次

    Nginx是一个异步框架的 Web服务器,也可以用作反向代理,负载平衡器 和 HTTP缓存。下载地址:www.nginx.org

    • 当我们实际用的时候需要先在配置文件中配置反向代理及负载均衡和日志格式和文件地址。我nginx安装地址为/soft/nginx,nginx编译安装好之后会有多份nginx.conf文件,一份为/soft/nginx/nginx.conf;另一份为/soft/nginx/conf/nginx.conf。如果服务器中存在多个nginx.conf文件,我们并不知道实际上调用的是哪个配置文件,因此我们必须找到实际调用的配置文件才能进行修改。

    查看nginx实际调用的配置文件

    1. 查看nginx路径
    [centos@bogon nginx]$ ps -aux|grep nginx
    root      22591  0.0  0.0  25008  1656 ?        Ss   Nov07   0:00 nginx: master process /soft/nginx/sbin/nginx
    centos    23716  0.0  0.1  25376  1916 ?        S    19:54   0:00 nginx: worker process
    centos    23824  0.0  0.0 112708   968 pts/1    S+   22:06   0:00 grep --color=auto nginx
    

    nginx的路径为:/soft/nginx/sbin/nginx

    1. 查看nginx配置文件路径
      使用nginx的 -t 参数进行配置检查,即可知道实际调用的配置文件路径及是否调用有效。
    [centos@bogon nginx]$ sudo /soft/nginx/sbin/nginx -t
    nginx: the configuration file /soft/nginx/nginx.conf syntax is ok
    nginx: configuration file /soft/nginx/nginx.conf test is successful
    
    

    可知,nginx的配置文件路径为:/soft/nginx/nginx.conf 且调用有效。

    修改nginx.conf 进行个性化配置,以达到日志动态分发

    我的需求:根据请求url里面个别关键字不同将请求日志记录到不同日志文件中。
    先看看菜鸟教程关于nginx.conf参数的讲解:http://www.runoob.com/w3cnote/nginx-install-and-config.html

    1. 访问日志参数
      Nginx访问日志主要有两个参数控制
    • log_format ----用来定义记录日志的格式(可以定义多种日志格式,取不同名字即可)
    • access_log -----用来指定日至文件的路径及使用的何种日志格式记录日志
      log_format的默认值:
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                         '"$http_user_agent" "$http_x_forwarded_for"';
    

    access_log的默认值:

    access_log  logs/access.log  main;
    

    log_format语法格式及参数语法说明如下:

     log_format    <NAME>    <Strin­­­g>;
        关键字         格式标签   日志格式
        关键字:其中关键字error_log不能改变
        格式标签:格式标签是给一套日志格式设置一个独特的名字
        日志格式:给日志设置格式
    log_format格式变量:
        $remote_addr  #记录访问网站的客户端地址
        $remote_user  #远程客户端用户名
        $time_local  #记录访问时间与时区
        $request  #用户的http请求起始行信息
        $status  #http状态码,记录请求返回的状态码,例如:200、301、404等
        $body_bytes_sent  #服务器发送给客户端的响应body字节数\
        $http_referer  #记录此次请求是从哪个连接访问过来的,可以根据该参数进行防盗链设置。
        $http_user_agent  #记录客户端访问信息,例如:浏览器、手机客户端等
        $http_x_forwarded_for  #当前端有代理服务器时,设置web节点记录客户端地址的配置,此参数生效的前提是代理服务器也要进行相关的x_forwarded_for设置
    

    access_log语法格式及参数语法说明如下:

     access_log    <FILE>    <NAME>;
        关键字         日志文件   格式标签
        关键字:其中关键字error_log不能改变
        日志文件:可以指定任意存放日志的目录
        格式标签:给日志文件套用指定的日志格式
    其他语法:
        access_log    off;  #关闭access_log,即不记录访问日志
        access_log path [format [buffer=size [flush=time]] [if=condition]];
        access_log path format gzip[=level] [buffer=size] [flush=time] [if=condition];
        access_log syslog:server=address[,parameter=value] [format [if=condition]];
        说明:
        buffer=size  #为存放访问日志的缓冲区大小
        flush=time  #为缓冲区的日志刷到磁盘的时间
        gzip[=level]  #表示压缩级别
        [if = condition]  #表示其他条件
    
    1. Nginx内置变量以及日志格式变量参数详解
    $args                    #请求中的参数值
    $query_string            #同 $args
    $arg_NAME                #GET请求中NAME的值
    $is_args                 #如果请求中有参数,值为"?",否则为空字符串
    $uri                     #请求中的当前URI(不带请求参数,参数位于$args),可以不同于浏览器传递的$request_uri的值,它可以通过内部重定向,或者使用index指令进行修改,$uri不包含主机名,如"/foo/bar.html"。
    $document_uri            #同 $uri
    $document_root           #当前请求的文档根目录或别名
    $host                    #优先级:HTTP请求行的主机名>"HOST"请求头字段>符合请求的服务器名.请求中的主机头字段,如果请求中的主机头不可用,则为服务器处理请求的服务器名称
    $hostname                #主机名
    $https                   #如果开启了SSL安全模式,值为"on",否则为空字符串。
    $binary_remote_addr      #客户端地址的二进制形式,固定长度为4个字节
    $body_bytes_sent         #传输给客户端的字节数,响应头不计算在内;这个变量和Apache的mod_log_config模块中的"%B"参数保持兼容
    $bytes_sent              #传输给客户端的字节数
    $connection              #TCP连接的序列号
    $connection_requests     #TCP连接当前的请求数量
    $content_length          #"Content-Length" 请求头字段
    $content_type            #"Content-Type" 请求头字段
    $cookie_name             #cookie名称
    $limit_rate              #用于设置响应的速度限制
    $msec                    #当前的Unix时间戳
    $nginx_version           #nginx版本
    $pid                     #工作进程的PID
    $pipe                    #如果请求来自管道通信,值为"p",否则为"."
    $proxy_protocol_addr     #获取代理访问服务器的客户端地址,如果是直接访问,该值为空字符串
    $realpath_root           #当前请求的文档根目录或别名的真实路径,会将所有符号连接转换为真实路径
    $remote_addr             #客户端地址
    $remote_port             #客户端端口
    $remote_user             #用于HTTP基础认证服务的用户名
    $request                 #代表客户端的请求地址
    $request_body            #客户端的请求主体:此变量可在location中使用,将请求主体通过proxy_pass,fastcgi_pass,uwsgi_pass和scgi_pass传递给下一级的代理服务器
    $request_body_file       #将客户端请求主体保存在临时文件中。文件处理结束后,此文件需删除。如果需要之一开启此功能,需要设置client_body_in_file_only。如果将次文件传 递给后端的代理服务器,需要禁用request body,即设置proxy_pass_request_body off,fastcgi_pass_request_body off,uwsgi_pass_request_body off,or scgi_pass_request_body off
    $request_completion      #如果请求成功,值为"OK",如果请求未完成或者请求不是一个范围请求的最后一部分,则为空
    $request_filename        #当前连接请求的文件路径,由root或alias指令与URI请求生成
    $request_length          #请求的长度 (包括请求的地址,http请求头和请求主体)
    $request_method          #HTTP请求方法,通常为"GET"或"POST"
    $request_time            #处理客户端请求使用的时间,单位为秒,精度毫秒; 从读入客户端的第一个字节开始,直到把最后一个字符发送给客户端后进行日志写入为止。
    $request_uri             #这个变量等于包含一些客户端请求参数的原始URI,它无法修改,请查看$uri更改或重写URI,不包含主机名,例如:"/cnphp/test.php?arg=freemouse"
    $scheme                  #请求使用的Web协议,"http" 或 "https"
    $server_addr             #服务器端地址,需要注意的是:为了避免访问linux系统内核,应将ip地址提前设置在配置文件中
    $server_name             #服务器名
    $server_port             #服务器端口
    $server_protocol         #服务器的HTTP版本,通常为 "HTTP/1.0" 或 "HTTP/1.1"
    $status                  #HTTP响应代码
    $time_iso8601            #服务器时间的ISO 8610格式
    $time_local              #服务器时间(LOG Format 格式)
    $cookie_NAME             #客户端请求Header头中的cookie变量,前缀"$cookie_"加上cookie名称的变量,该变量的值即为cookie名称的值
    $http_NAME               #匹配任意请求头字段;变量名中的后半部分NAME可以替换成任意请求头字段,如在配置文件中需要获取http请求头:"Accept-Language",$http_accept_language即可
    $http_cookie
    $http_host               #请求地址,即浏览器中你输入的地址(IP或域名)
    $http_referer            #url跳转来源,用来记录从那个页面链接访问过来的
    $http_user_agent         #用户终端浏览器等信息
    $http_x_forwarded_for
    $sent_http_NAME          #可以设置任意http响应头字段;变量名中的后半部分NAME可以替换成任意响应头字段,如需要设置响应头Content-length,$sent_http_content_length即可
    $sent_http_cache_control
    $sent_http_connection
    $sent_http_content_type
    $sent_http_keep_alive
    $sent_http_last_modified
    $sent_http_location
    $sent_http_transfer_encoding
    

    当日志文件中记录的值为"-"时,表示为空.

    1. nginx.conf 自定义变量使用详解
      在使用Nginx作为网站的web服务器的时候,为了达到某些效果或者是为了优化Nginx服务器的效率,经常要修改Nginx的配置文件Nginx.conf。
      在 Nginx 配置中,自定义变量只能存放一种类型的值,因为也只存在一种类型的值,那就是字符串
      比如我们的 nginx.conf 文件中有下面这一行配置
    set $a "hello world";  
    

    set 配置指令为对 $a 赋值。特别地,我们把字符串 hello world 赋给了它。
    同样的,如果我们要根据自定义变量达到一些个性化的需求,可以在变量赋值之后做一些判断赋值定义等操作。这时候可能需要if语句判断,比如:

    if ( $host ~* www\.(.*) )
      {
        set  $host_without_www $1;
      }
    

    但是要注意:if语句只有在server,location代码块中才能使用。
    在这里我们了解一下NginxRewrite 规则相关指令:

    1.break指令
        使用环境:server,location,if;
        该指令的作用是完成当前的规则集,不再处理rewrite指令。
    
      2.if指令
        使用环境:server,location
        该指令用于检查一个条件是否符合,如果条件符合,则执行大括号内的语句。If指令不支持嵌套,不支持多个条件&&和||处理。
    
    3.return指令
      语法:return code ;
      使用环境:server,location,if;
      该指令用于结束规则的执行并返回状态码给客户端。
      示例:如果访问的URL以".sh"或".bash"结尾,则返回403状态码
      location ~ .*\.(sh|bash)?$
      {
        return 403;
      }
    
    4.rewrite 指令
      语法:rewriteregex replacement flag
      使用环境:server,location,if
      该指令根据表达式来重定向URI,或者修改字符串。指令根据配置文件中的顺序来执行。注意重写表达式只对相对路径有效。如果你想配对主机名,你应该使用if语句,示例如下:
      if ( $host ~* www\.(.*) )
      {
        set  $host_without_www $1;
        rewrite  ^(.*)$   http://$host_without_www$1 permanent;
      }
    
    5.Set指令
      语法:setvariable value ; 默认值:none; 使用环境:server,location,if;
      该指令用于定义一个变量,并给变量赋值。变量的值可以为文本、变量以及文本变量的联合。
      示例:set $varname "hello world";
    
    6.Uninitialized_variable_warn指令
      语法:uninitialized_variable_warnon|off
      使用环境:http,server,location,if
      该指令用于开启和关闭未初始化变量的警告信息,默认值为开启。
    

    下面都是一些Nginx的Rewrite规则编写实例

     1.当访问的文件和目录不存在时,重定向到某个php文件
        if ( !-e $request_filename )
        {
          rewrite ^/(.*)$ index.php last;
        }
    
      2.目录对换 /123456/xxxx ====> /xxxx?id=123456
        rewrite ^/(\d+)/(.+)/ /$2?id=$1 last;
    
      3.如果客户端使用的是IE浏览器,则重定向到/ie目录下
        if( $http_user_agent ~ MSIE)
        {
          rewrite ^(.*)$ /ie/$1 break;
        }
    
      4.禁止访问多个目录
        location ~ ^/(cron|templates)/
        {
          deny all;
          break;
        }
    
    
      5.禁止访问以/data开头的文件
        location ~ ^/data
        {
          deny all;
        }
    
    
      6.禁止访问以.sh,.flv,.mp3为文件后缀名的文件
        location ~ .*\.(sh|flv|mp3)$
        {
          return 403;
        }
    
    
      7.设置某些类型文件的浏览器缓存时间
        location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
        {
          expires 30d;
        }
        location ~ .*\.(js|css)$
        {
          expires 1h;
        }
    
    
    8.给favicon.ico和robots.txt设置过期时间;
      这里为favicon.ico为99天,robots.txt为7天并不记录404错误日志
       location ~(favicon.ico)
      {
        log_not_found off;
        expires 99d;
        break;
      }
      location ~(robots.txt)
      {
        log_not_found off;
        expires 7d;
        break;
      }
    
    9.设定某个文件的过期时间;这里为600秒,并不记录访问日志
      location ^~ /html/scripts/loadhead_1.js
      {
        access_log off;
        root /opt/lampp/htdocs/web;
        expires 600;
        break;
      }
    
    
    10.文件反盗链并设置过期时间
      这里的return412 为自定义的http状态码,默认为403,方便找出正确的盗链的请求
      “rewrite ^/ http://img.linuxidc.net/leech.gif;” 显示一张防盗链图片
      “access_log off;” 不记录访问日志,减轻压力
      “expires 3d”  所有文件3天的浏览器缓存
      location ~*^.+\.(jpg|jpeg|gif|png|swf|rar|zip|css|js)$
      {
        valid_referers none blocked *.linuxidc.com*.linuxidc.net localhost 208.97.167.194;
        if ($invalid_referer)
        {
          rewrite ^/ http://img.linuxidc.net/leech.gif;
          return 412;
          break;
        }
        access_log off;
        root /opt/lampp/htdocs/web;
        expires 3d;
        break;
      }
    
    
    11.只允许固定ip访问网站,并加上密码
      root /opt/htdocs/www;
      allow 208.97.167.194;
      allow 222.33.1.2;
      allow 231.152.49.4;
      deny all;
      auth_basic “C1G_ADMIN”;
      auth_basic_user_file htpasswd;
    
    
    12将多级目录下的文件转成一个文件,增强seo效果
      /job-123-456-789.html 指向/job/123/456/789.html
      rewrite ^/job-([0-9]+)-([0-9]+)-([0-9]+)\.html$ /job/$1/$2/jobshow_$3.html last;
    
    
    13.文件和目录不存在的时候重定向:
      if (!-e $request_filename)
    
       {
        proxy_pass http://127.0.0.1;
      }
    
    
    14.将根目录下某个文件夹指向2级目录
      如/shanghaijob/ 指向 /area/shanghai/
      如果你将last改成permanent,那么浏览器地址栏显是/location/shanghai/
      rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
      上面例子有个问题是访问/shanghai时将不会匹配
      rewrite ^/([0-9a-z]+)job$ /area/$1/ last;
      rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
      这样/shanghai 也可以访问了,但页面中的相对链接无法使用,
      如./list_1.html真实地址是/area/shanghia/list_1.html会变成/list_1.html,导至无法访问。
      那我加上自动跳转也是不行咯
      (-d $request_filename)它有个条件是必需为真实目录,而我的rewrite不是的,所以没有效果
      if (-d $request_filename)
      {
        rewrite ^/(.*)([^/])$ http://$host/$1$2/permanent;
      }
      知道原因后就好办了,让我手动跳转吧
      rewrite ^/([0-9a-z]+)job$ /$1job/permanent;
      rewrite ^/([0-9a-z]+)job/(.*)$ /area/$1/$2last;
    
    
    15.域名跳转
      server
      {
        listen 80;
        server_name jump.linuxidc.com;
        index index.html index.htm index.php;
        root /opt/lampp/htdocs/www;
        rewrite ^/ http://www.linuxidc.com/;
        access_log off;
      }
    
    
    16.多域名转向
      server_name www.linuxidc.com www.linuxidc.net;
      index index.html index.htm index.php;
      root /opt/lampp/htdocs;
      if ($host ~ "linuxidc\.net") {
        rewrite ^(.*) http://www.linuxidc.com$1permanent;
      }
    
    1. nginx正则表达式匹配
      正则匹配:
    1、~ 区分大小写匹配
    2、~* 不区分大小写匹配
    3、!~和!~*分别为区分大小写不匹配及不区分大小写不匹配
    4、^ 以什么开头的匹配
    5、$ 以什么结尾的匹配
    6、.*:   .匹配任意字符,*匹配数量0到正无穷;
    7、\. 斜杠用来转义,\.匹配 .    特殊使用方法,记住记性了;
    8、(值1|值2|值3|值4):或匹配模式,例:(jpg|gif|png|bmp)匹配jpg或gif或png或bmp
    

    文件及目录匹配:

         -f和!-f用来判断是否存在文件
         -d和!-d用来判断是否存在目录
         -e和!-e用来判断是否存在文件或目录
         -x和!-x用来判断文件是否可执行
    

    使用excemple:

    location = /
    #匹配任何查询,因为所有请求都已 / 开头。但是正则表达式规则和长的块规则将被优先和查询匹配
    location ^~ /images/ {
    # 匹配任何已/images/开头的任何查询并且停止搜索。任何正则表达式将不会被测试。
    location ~* .(gif|jpg|jpeg)$ {
    # 匹配任何已.gif、.jpg 或 .jpeg 结尾的请求
    

    博客标题解决方案:

    1. 先观察请求url
      http://www.kouyy1.com/args?arg1=yiche&arg2=click
    2. 需求:要根据arg2=后面的参数值动态分发日志
      解决思路:?后面的一长串都属于nginx.conf内置变量里的args,可以根据正则匹配args后面的内容。
    log_format  main  '$remote_addr  $remote_user [$time_local] "$request" '
                    '$request_method $request_uri  $args  $uri' 
                               '$status $body_bytes_sent "$http_referer" '
                              '"$http_user_agent" "$http_x_forwarded_for"';     
    server {
            listen       80;
            server_name  www.kouyy1.com;
        
            location / {
               proxy_pass        http://192.168.70.34:8080;  
                       proxy_set_header   Host             $host;  
                       proxy_set_header   X-Real-IP        $remote_addr;  
                       proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;  
               
               set  $log_name  "access";
               
               if ($args ~* (.*)arg2=click(.*)){
               set $log_name "click";
              }
               if ($args ~* (.*)arg2=view(.*)){
               set $log_name "view";
              }
               if ($args ~* (.*)arg2=look(.*)){
               set $log_name "look";
              }
               if ($args ~* (.*)arg2=content(.*)){
               set $log_name "content";
              }
               access_log  logs/$log_name.log  main;
            }
            error_page   500 502 503 504  /50x.html;
            location = /50x.html {
                root   html;
            }
        }
    
    1. 配置文件重写之后重启Nginx
      发出请求:
      http://www.kouyy1.com/args?arg1=yiche&arg2=click
      http://www.kouyy1.com/args?arg1=yiche&arg2=look
      http://www.kouyy1.com/args?arg1=yiche&arg2=content
      http://www.kouyy1.com/args?arg1=yiche&arg2=view
      http://www.kouyy1.com/args?arg1=yiche&arg2=hello
    [centos@bogon logs]$ ll
    total 124
    -rw-r--r--. 1 centos centos 63768 Nov  8 19:56 access.log
    -rw-r--r--. 1 centos centos  2779 Nov  7 19:15 analysis_log.py
    -rw-r--r--. 1 centos centos   275 Nov  8 19:54 click.log
    -rw-r--r--. 1 centos centos   281 Nov  8 19:54 content.log
    -rw-r--r--. 1 centos centos 27446 Nov  8 22:08 error.log
    -rw-r--r--. 1 centos centos   544 Nov  8 19:55 look.log
    -rw-r--r--. 1 root   root       6 Nov  7 22:45 nginx.pid
    -rw-r--r--. 1 centos centos   272 Nov  8 19:55 view.log
    

    可以看出实现了日志动态分发。

    参考文章

    1. https://www.cnblogs.com/czlun/articles/7010591.html
    2. https://blog.csdn.net/czlun/article/details/73251723
    3. https://www.cnblogs.com/wajika/p/6426270.html
    4. https://yq.aliyun.com/ziliao/46471?spm=a2c4e.11155472.blogcont.29.48c6323ckLnKSx
    5. https://www.cnblogs.com/xuey/p/7631690.html
    6. https://blog.csdn.net/scdxmoe/article/details/52094350

    相关文章

      网友评论

        本文标题:nginx配置自定义变量实现日志动态分发

        本文链接:https://www.haomeiwen.com/subject/vdxoxqtx.html