相关推荐recommended
Nginx 日志配置
作者:mmseoamin日期:2024-04-27

☁️ Nginx 日志配置

日志是用来进行数据统计、问题排错的重要手段。在Nginx中,日志相关的配置非常灵活且功能丰富。本文将详细介绍Nginx中与日志相关的配置。


1️⃣ 日志相关配置

Nginx中与日志相关的配置包括:

  • access_log:访问日志
  • log_format:日志格式
  • rewrite_log:重定向日志
  • error_log:错误日志

    每个级别的配置可以有其独立的访问日志,而日志格式则可以通过log_format命令来自定义。


    2️⃣ access_log 配置详解

    在Nginx中,access_log指令用于定义如何记录客户端的请求。这些日志通常对分析网站流量、性能调优等非常有用。

    🟢 语法:

    access_log path [format [buffer=size [flush=time]]];
    access_log path format gzip[=level] [buffer=size] [flush=time];
    access_log syslog:server=address[,parameter=value] [format];
    access_log off; # 不记录日志
    

    🟢 参数详解:

    1. path:

      • 这是日志文件的存储路径。可以是绝对路径或相对于Nginx的安装目录的路径。
      • format:

        • 这是日志的格式。它可以是预先定义的(如combined),也可以是使用log_format指令自定义的格式。
        • buffer=size:

          • 这指定了在写入硬盘之前,日志消息应缓存在内存中的大小。这可以减少磁盘I/O,提高性能。
          • 例如,buffer=32k意味着在写入硬盘之前,将缓存32KB的日志消息。
          • flush=time:

            • 尽管缓冲区可能尚未满,但这指定了在缓冲区被刷新到硬盘之前的最大时间。
            • 例如,flush=10s意味着即使缓冲区未满,也会每10秒将其内容写入硬盘。
            • gzip[=level]:

              • 这使得Nginx在写入硬盘之前压缩日志。
              • level是压缩等级,范围是1(最低压缩,最快速度)到9(最高压缩,最慢速度)。
              • syslog:server=address[,parameter=value]:

                • 这使Nginx将日志发送到指定的syslog服务器,而不是写入本地文件。
                • address是syslog服务器的地址,parameter=value是其他可选参数。
                • off:

                  • 这禁用了访问日志的记录。

    🟢 默认配置:

    如果没有为access_log指定格式,则默认使用combined格式。这是一个常用的格式,与Apache的combined格式相似。

    access_log logs/access.log combined;
    

    使用access_log可以帮助您详细跟踪Nginx服务器的访问模式,这对于诊断问题、分析流量和监视安全性都非常有用。以下是一些在各个层级中使用access_log的示例配置:


    🟢 配置示例:

    🔶 1. 在http级别:

    这会影响所有的服务器(server)和位置(location)块,除非它们有自己的access_log定义。

    http {
        access_log /var/log/nginx/global_access.log combined;
        ...
    }
    

    🔶 2. 在server级别:

    只会影响这个特定的server块。

    server {
        listen 80;
        server_name example.com;
        
        access_log /var/log/nginx/example.com_access.log combined;
        ...
    }
    

    🔶 3. 在location级别:

    这会影响这个特定的location块。

    server {
        ...
        location /api/ {
            access_log /var/log/nginx/api_access.log combined;
            ...
        }
        location /static/ {
            access_log off;  # 不记录静态内容的访问日志
            ...
        }
    }
    

    🔶 4. 特定的日志格式:

    在http级别定义一个自定义的日志格式,然后在server或location级别使用它。

    http {
        log_format main_extended '$remote_addr - $remote_user [$time_local] "$request" '
                                 '$status $body_bytes_sent "$http_referer" '
                                 '"$http_user_agent" "$http_x_forwarded_for"';
        server {
            ...
            location / {
                access_log /var/log/nginx/special_access.log main_extended;
                ...
            }
        }
    }
    

    🔶 5. 记录到syslog服务器:

    这是一个在server级别将访问日志发送到syslog服务器的示例。

    server {
        ...
        access_log syslog:server=192.168.1.100,facility=local7,tag=nginx combined;
    }
    

    🔶 6. 使用条件记录日志:

    这是一个只记录返回404状态码的请求的示例。

    map $status $loggable {
        ~^[23]  0;
        default 1;
    }
    server {
        ...
        access_log /var/log/nginx/404s.log combined if=$loggable;
    }
    

    3️⃣ log_format 配置详解

    在Nginx中,log_format指令允许您自定义日志的输出格式,这对于满足特定日志解析工具的要求或提供更多的日志详情非常有用。

    🟢 语法:

    log_format name string ……;
    
    • name:定义日志格式的名称,这样您就可以在其他配置段中通过这个名称引用它。
    • string:定义日志的具体格式。这通常包括多个变量,由空格分隔。

      🟢 默认配置:

      Nginx提供了一个名为combined的默认日志格式,它非常接近Apache的同名格式:

      log_format combined '$remote_addr - $remote_user [$time_local] '
                          '"$request" $status $body_bytes_sent '
                          '"$http_referer" "$http_user_agent"';
      

      🟢 常用变量解释:

      • $remote_addr:客户端的IP地址。
      • $remote_user:通过HTTP基本认证的客户端用户名。
      • $time_local:本地时间,通常用于记录请求到达的时间。
      • $request:客户端的完整请求行,通常包括HTTP方法、请求的URI和HTTP版本。
      • $status:响应的HTTP状态码。
      • $body_bytes_sent:发送到客户端的响应体的字节数。
      • $http_referer:引发请求的页面的URL(如果有的话)。
      • $http_user_agent:客户端浏览器的用户代理字符串。

        还有许多其他的变量可以用于log_format,例如$http_host(请求的主机名)、$request_time(请求处理时间)等。选择哪些变量取决于您希望从日志中获取哪些信息。


        🟢 示例配置:

        log_format 指令使您可以自定义 Nginx 的日志输出格式。这在多种场景中非常有用,例如当您需要与特定的日志分析工具集成,或者需要更多详细的日志信息时。

        以下是一些在不同场景中使用 log_format 的示例配置:

        🔶 1. 默认的 combined 格式:

        这是 Nginx 提供的默认日志格式,与 Apache 的 combined 格式非常相似。

        log_format combined '$remote_addr - $remote_user [$time_local] '
                            '"$request" $status $body_bytes_sent '
                            '"$http_referer" "$http_user_agent"';
        

        🔶 2. 扩展的日志格式:

        此格式提供了与 combined 格式相似的信息,并增加了几个额外的字段,如请求时间和连接请求次数。

        log_format main_extended '$remote_addr - $remote_user [$time_local] '
                                 '"$request" $status $body_bytes_sent '
                                 '"$http_referer" "$http_user_agent" '
                                 'request_time=$request_time connection_requests=$connection_requests';
        

        🔶 3. JSON 格式:

        此格式可以与现代日志分析工具(如 ELK Stack 或 Graylog)结合使用,这些工具通常更容易解析 JSON 格式的日志。

        log_format json_combined '{'
            '"remote_addr":"$remote_addr",'
            '"remote_user":"$remote_user",'
            '"time_local":"$time_local",'
            '"request":"$request",'
            '"status":$status,'
            '"body_bytes_sent":$body_bytes_sent,'
            '"http_referer":"$http_referer",'
            '"http_user_agent":"$http_user_agent"'
        '}';
        

        🔶 4. 为缓存状态定制的格式:

        当您使用 Nginx 作为反向代理和缓存服务器时,此格式可以帮助您跟踪缓存的行为。

        log_format cache_status '$remote_addr - $remote_user [$time_local] '
                                '"$request" $status $body_bytes_sent '
                                '"$http_referer" "$http_user_agent" '
                                'cache_status=$upstream_cache_status';
        

        如何在配置中使用 log_format:

        定义完 log_format 后,您可以在 http、server 或 location 配置块中使用 access_log 指令来引用它。

        例如,使用上面定义的 json_combined 格式:

        server {
            ...
            access_log /var/log/nginx/access_json.log json_combined;
        }
        

        4️⃣ rewrite_log 配置详解

        Nginx中的rewrite_log指令是用于控制是否记录URL重写日志的。当您使用rewrite指令来改变请求的URI或进行其他URL重写操作时,这个日志可以帮助您跟踪和调试这些操作。

        🟢 语法:

        rewrite_log on | off;
        
        • on:启用重写日志
        • off:禁用重写日志

          🟢 默认配置:

          默认情况下,rewrite_log是关闭的,即:

          rewrite_log off;
          

          这意味着在默认设置下,Nginx不会记录任何与URL重写相关的日志信息。

          🟢 功能与用途:

          rewrite_log指令是由ngx_http_rewrite_module模块提供的,该模块为Nginx提供了强大的URL重写功能。

          当您在配置文件中使用rewrite指令进行URL重写或重定向时,启用rewrite_log可以帮助您了解重写规则是如何被应用的,尤其是在处理复杂的重写逻辑时。

          例如,如果您有一个重写规则将所有/old-path/下的请求重定向到/new-path/,并且某些请求没有按预期进行重定向,那么启用rewrite_log就非常有用。

          🟢 示例配置:

          🔶 1. 在 http 级别启用 rewrite_log:

          此配置将对所有的 server 和 location 块生效,除非它们有自己的 rewrite_log 配置。

          http {
              rewrite_log on;
              ...
          }
          
          🔶 2. 在特定 server 块中启用 rewrite_log:

          这将仅影响此特定 server 块。

          server {
              listen 80;
              server_name example.com;
              rewrite_log on;
              ...
          }
          
          🔶 3. 在特定 location 块中启用 rewrite_log:

          这将仅影响此特定 location 块。

          server {
              ...
              location /api/ {
                  rewrite_log on;
                  ...
              }
          }
          

          🟢 注意事项:

          1. 当rewrite_log设置为on时,相关的日志信息将以notice级别记录在error log中。
          2. 频繁的URL重写可能会生成大量的日志,这可能会影响到日志文件的大小和磁盘使用情况。因此,在生产环境中,建议在解决问题后禁用rewrite_log。
          3. 虽然rewrite_log是一个很好的调试工具,但在生产环境中长时间启用它可能不是一个好主意,因为它可能会产生不必要的I/O操作和额外的性能开销。

          5️⃣ error_log 配置详解

          在Nginx中,error_log指令是用于定义错误日志的存储位置和记录级别的。错误日志是系统管理员和开发人员诊断问题、监视系统行为的关键工具。

          🟢 语法:

          error_log file | stderr | syslog:server=address[,parameter=value] [debug | info | notice | warn | error | crit | alert | emerg];
          

          🟢 参数详解:

          1. file:

            • 错误日志文件的路径。它可以是相对路径(相对于Nginx安装目录)或绝对路径。
            • stderr:

              • 这使得日志消息被写入标准错误输出。
              • syslog:server=address[,parameter=value]:

                • 这使Nginx将日志消息发送到指定的syslog服务器。
                • address是syslog服务器的地址。
                • parameter=value可以是其他的可选参数,如facility、tag等。
                • debug | info | notice | warn | error | crit | alert | emerg:

                  • 这些是日志级别,从最详细的debug到最关键的emerg。
                  • 选择的级别确定了哪些消息会被记录。例如,选择warn会记录警告、错误、严重错误、警报和紧急消息,但不会记录调试、信息和通知消息。

          🟢 默认配置:

          如果没有明确指定,Nginx会使用以下默认配置:

          error_log logs/error.log error;
          

          这意味着错误日志将被写入logs/error.log文件,并记录级别为error的消息及其以上的级别。

          🟢 使用示例:

          🔶 1. 在 http 级别配置 error_log:

          此配置将对所有的 server 块生效,除非它们有自己的 error_log 配置。

          http {
              error_log /var/log/nginx/main_error.log warn;
              ...
          }
          
          🔶 2. 在特定 server 块中配置 error_log:

          此配置仅影响此特定 server 块。

          server {
              listen 80;
              server_name example.com;
              error_log /var/log/nginx/example.com_error.log warn;
              ...
          }
          
          🔶 3. 为某些地方启用详细的日志记录:

          如果某个 location 处理敏感的操作或频繁出错,您可能希望为它启用更详细的日志记录。

          server {
              ...
              location /api/ {
                  error_log /var/log/nginx/api_error.log info;
                  ...
              }
          }
          
          🔶 4. 使用 syslog 发送错误日志:

          此配置将错误日志发送到指定的 syslog 服务器。

          error_log syslog:server=192.168.1.100,facility=local7,tag=nginx warn;
          
          🔶 5. 在 location 级别禁用 error_log:

          有时,您可能不希望为某个特定的 location 记录错误日志。

          location /static/ {
              error_log /dev/null crit;
              ...
          }
          

          注意:这里我们使用 /dev/null 作为路径,这意味着所有的日志都被丢弃,并设置日志级别为 crit,这意味着只有严重的错误才会被记录(但由于路径是 /dev/null,所以实际上不会有任何记录)。


          🟢 注意事项:

          • 选择合适的日志级别是很重要的。在开发环境中,使用 debug 级别可能很有帮助,但在生产环境中,这可能会导致大量的日志输出和性能开销。

          • 定期检查和清理您的错误日志,以确保它们不会消耗所有的磁盘空间。

          • 如果您使用的是外部日志系统(如 ELK Stack 或 Graylog),确保您的 Nginx 配置与之兼容。


            🧲 Nginx 日志切割


            由于 Nginx 自身没有内置日志切割功能,所以长时间运行的 Nginx 实例的日志文件可能会变得非常大。为了管理这些日志,我们可以创建一个脚本来定期切割它们。

            🔍 切割逻辑概述:

            1. 📂 重命名当前日志文件:我们可以将 access.log 重命名为日期格式,如 access_20211012.log。即使文件已重命名,Nginx 仍会继续向该文件写日志,直到它被告知要使用一个新的日志文件。

            2. 📡 发送信号给 Nginx:通过向 Nginx 主进程发送 USR1 信号,Nginx 会重新打开日志文件。此时,Nginx 会停止向旧的(已重命名的)日志文件写入,并开始向新的 access.log 文件写入。

            🔧 日志切割脚本:

            以下是一个简单的 bash 脚本来实现上述逻辑:

            #!/bin/bash
            # 📁 日志文件的路径
            logs_path='/usr/local/nginx/logs/'
            # 🔑 Nginx 的 PID 文件路径
            pid_path='/usr/local/nginx/nginx.pid'
            # 🔄 重命名当前的日志文件
            mv ${logs_path}access.log ${logs_path}access_$(date -d 'yesterday' +'%Y%m%d').log
            # 🚀 通过发送 USR1 信号来告诉 Nginx 重新打开日志文件
            kill -USR1 `cat ${pid_path}`
            

            ⏰ 自动化日志切割:

            为了自动执行上述脚本,我们可以使用 cron 来定期运行它。例如,下面的 crontab 任务会每天凌晨 12 点执行上述脚本:

            0 0 * * * bash /path_to_script/nginx_log.sh
            

            💡 确保您已为脚本设置了可执行权限,并将 /path_to_script/ 替换为您保存脚本的实际路径。