NOTE · Engineering Systems

Nginx 路径映射与日志排查备忘

从 root 与 alias 的路径映射讲起,汇总静态站点配置和日志排查方法。

root 和 alias 区别

在 Nginx 配置中,rootalias 都是用于指定文件的路径,但它们有一些关键的区别。理解这两者的差异有助于正确配置 Nginx 以处理不同的文件路径。

root 指令

  • 作用root 用于指定一个目录作为请求路径的根目录。也就是说,它是将请求的 URI(路径)与文件系统中的实际路径进行映射。
  • 路径映射root 将请求的 URI 拼接到该目录之后。Nginx 会将请求的 URL 中的路径部分与指定的 root 目录进行组合,生成实际的文件路径。
  • 应用场景:通常用于指定 Web 服务器的根目录,比如 HTML 文件和其他静态资源的存放位置。

示例:

location /images/ {
    root /var/www/html;  # 将请求 /images/logo.png 映射为 /var/www/html/images/logo.png
}
  • 如果客户端请求 http://example.com/images/logo.png,Nginx 会尝试在 /var/www/html/images/logo.png 找到文件。

alias 指令

  • 作用alias 用于指定一个路径,并将请求的 URI 映射到该路径。alias 不会将请求的 URI 拼接到目录后面,而是将整个 URI 替换为指定的目录。
  • 路径映射alias 会将请求路径完全替换为指定的目录。因此,它只会对一个 location 内部有效,特别适合用在访问某些目录的别名或静态文件的目录重定向。
  • 应用场景:适用于静态文件的目录映射,尤其是当请求的 URI 部分需要被替换的情况。

示例:

location /static/ {
    alias /var/www/assets/;  # 将请求 /static/logo.png 映射为 /var/www/assets/logo.png
}
  • 如果客户端请求 http://example.com/static/logo.png,Nginx 会尝试在 /var/www/assets/logo.png 找到文件。
  • 注意,这里 /static/ 会被替换为 /var/www/assets/,而不会继续拼接路径。
  • 目录映射时通常让 location /static/alias /var/www/assets/ 的尾部斜杠保持一致,避免边界路径产生意外映射。

先把映射写成字符串替换,最不容易混淆:

root:  /var/www/html + /images/logo.png
       -> /var/www/html/images/logo.png

alias: /static/ 被 /var/www/assets/ 替换
       -> /var/www/assets/logo.png

精确文件也可使用 alias

location = /robots.txt {
    alias /srv/site-assets/robots.txt;
}

正则 location 中使用 alias 时通常需要捕获组,并在 alias 路径中引用;这种配置容易写错,应对每个边界 URI 做实际请求测试。静态目录还要核对 Nginx worker 对父目录和文件的遍历/读取权限,而不是遇到 403 就把目录改成全员可写。


查看 Nginx 的连接日志和错误日志

在管理 Nginx 服务器时,查看连接日志和错误日志是非常重要的。它们帮助你了解服务器的运行状况,发现潜在的问题,甚至优化性能。本文将详细介绍如何查看 Nginx 的连接日志和错误日志。

1. Nginx 日志文件的基本结构

Nginx 通常配置两类主要日志:

  • 访问日志(Access Logs):记录每个客户端请求的详细信息,如请求时间、请求路径、客户端 IP 等。
  • 错误日志(Error Logs):记录 Nginx 运行过程中出现的错误信息。

日志路径由编译参数和配置决定。Debian/Ubuntu 软件包中常见路径如下,但其他发行版、容器镜像或源码安装可能不同:

  • 访问日志:/var/log/nginx/access.log
  • 错误日志:/var/log/nginx/error.log

2. 查看 Nginx 访问日志

启用 access_log 时,访问日志会按请求最终处理位置所使用的格式记录请求。通常可包含客户端地址、请求 URL、响应状态码和请求耗时等信息。

一个常见的扩展日志格式示例

Nginx 内置名为 combined 的格式;下面的 main 是用户自定义示例,不应称为所有安装的默认格式:

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for" '
                  'rt=$request_time uct=$upstream_connect_time '
                  'uht=$upstream_header_time urt=$upstream_response_time';

access_log /var/log/nginx/access.log main;
  • $remote_addr:客户端 IP 地址
  • $remote_user:客户端身份验证的用户名
  • $time_local:请求时间
  • $request:请求的 URL 和 HTTP 协议
  • $status:HTTP 响应状态码
  • $body_bytes_sent:发送给客户端的响应体字节数
  • $http_referer:请求来源
  • $http_user_agent:客户端的浏览器或其他用户代理
  • $http_x_forwarded_for:原始请求头内容;客户端可以伪造,未经可信代理边界校验时不能直接当作真实客户端 IP
  • $request_time:Nginx 处理整个请求的总耗时
  • $upstream_connect_time$upstream_header_time$upstream_response_time:连接上游、等待响应头和接收上游响应的耗时

如果 Nginx 前面确有受控的反向代理或负载均衡器,应只信任它的地址范围。例如:

set_real_ip_from TRUSTED_PROXY_CIDR;
real_ip_header X-Forwarded-For;
real_ip_recursive on;

TRUSTED_PROXY_CIDR 必须替换为实际、受控的代理地址或网段,并确保该代理会覆盖或正确维护转发头。不要把整个互联网设为可信来源,否则攻击者可以伪造客户端地址。配置生效后,$remote_addr 才会按 realip 模块规则被替换;原始对端地址可从 $realip_remote_addr 获取。该模块也可能未被当前 Nginx 构建启用,可用 nginx -V 核对构建参数。

查看访问日志

查看 Nginx 的访问日志非常简单,只需要用 catlesstail 命令读取日志文件。

  • 查看日志的最新内容

    tail -f /var/log/nginx/access.log
    

    tail -f 会实时显示日志文件中新增的内容,非常适合查看实时的访问情况。

  • 查看日志的前几行

    head /var/log/nginx/access.log
    

    head 命令可以查看日志文件的前几行内容,帮助你快速了解日志格式。

  • 查看日志的指定部分

    less /var/log/nginx/access.log
    

    less 命令提供了一个分页显示的方式,适用于查看大文件。

3. 查看 Nginx 错误日志

Nginx 的错误日志记录了服务器运行时发生的错误,如启动失败、请求处理中的问题等。错误日志对于排查问题和诊断服务器配置或代码错误至关重要。

错误日志配置示例

下面配置的是路径和最低记录级别,不是 log_format 式的格式定义:

error_log /var/log/nginx/error.log warn;
  • 错误日志级别:
    • debug:记录详细的调试信息,适用于调试阶段。
    • info:记录常规信息,适用于常规日志。
    • notice:记录重要信息,通常表示系统的一些重要事件。
    • warn:记录警告信息,表示有可能影响服务器的事件,但不至于崩溃。
    • error:记录错误信息,通常表示会导致请求失败的问题。
    • crit:记录关键错误,通常是系统无法继续运行的严重问题。
    • alert:表示需要立即处理的严重错误。
    • emerg:紧急错误,系统无法继续工作。

查看错误日志

  • 查看错误日志的最新内容

    tail -f /var/log/nginx/error.log
    

    tail -f 让你可以实时查看日志中的新错误,非常适合用于故障排查。

  • 查看错误日志的前几行

    head /var/log/nginx/error.log
    
  • 使用 less 命令查看日志

    less /var/log/nginx/error.log
    

4. 日志分析和故障排查

结合访问日志和错误日志排查问题

有时,错误日志中的信息不足以帮助你完全解决问题,这时可以将访问日志和错误日志结合起来查看。例如:

  • 404 Not Found:先在访问日志中确认 URI、Host 和最终状态码,再核对 root/alias 映射、文件权限及内部重定向。
  • 502 Bad Gateway:表示 Nginx 从上游拿到无效响应或无法正常完成上游通信,常见线索包括连接被拒绝/重置、Unix socket 权限、上游进程退出、协议或 proxy_pass 配置错误。
  • 504 Gateway Timeout:表示等待上游响应超过配置的超时。先检查上游健康、实际响应耗时、依赖服务和网络,再判断是否需要调整超时。

高请求量可能是诱因之一,但状态码本身不能证明“请求太多”。应结合 $upstream_*_time、并发/资源指标、上游日志和同一时间段的错误日志定位。

修改配置后,先测试语法和引用文件,再重新加载:

sudo nginx -t
sudo systemctl reload nginx

只有 nginx -t 成功后才应执行 reload。若安装不由 systemd 管理,应使用对应运行方式的 reload 命令。nginx -T 可输出合并后的完整配置以帮助排查,但输出可能含域名、证书路径或其他敏感配置,不要原样发布。

软件包安装常可同时从 systemd journal 查看启动失败原因:

systemctl status nginx
journalctl -u nginx --since today

容器中的 Nginx 可能把日志写到标准输出/错误,而不是宿主机 /var/log/nginx;应先检查容器配置和日志驱动。

过滤日志

对于大规模的日志文件,使用 grep 命令进行日志过滤可以帮助你快速找到相关的信息。例如:

  • 查找特定 IP 地址的访问记录

    grep "CLIENT_IP" /var/log/nginx/access.log
    
  • 查找 404 错误的请求

    grep " 404 " /var/log/nginx/access.log
    
  • 查找特定时间段的日志

    grep "12/Dec/2025" /var/log/nginx/access.log
    

汇总状态码与慢请求

只有确认日志格式中相应字段位置后,才可用 awk 按列统计。对常见 combined 格式,状态码通常是第 9 列:

awk '{count[$9]++} END {for (code in count) print code, count[code]}' \
  /var/log/nginx/access.log | sort

自定义格式最好直接记录可识别字段,例如 status=$status rt=$request_time,再按键解析,避免 User-Agent 或带空格字段让固定列错位。

查看轮转后的压缩日志可用:

zgrep ' 404 ' /var/log/nginx/access.log*.gz

日志可能包含客户端地址、查询参数、Referer、User-Agent 以及认证后的用户名。公开故障样例前应做最小化截取和脱敏;应用也不应把 Token、密码或敏感正文放进 URL。

从请求到文件的验证顺序

  1. curl -Icurl -v 固定 Host、路径和协议,保存实际状态码;
  2. sudo nginx -T 确认命中的 server/location,而不是只看某一个配置文件;
  3. 手工拼出 rootalias 的目标路径;
  4. namei -l TARGET_PATH 检查每一级目录权限;
  5. 对反向代理再检查上游监听、协议和 $upstream_*_time
  6. 配置通过 nginx -t 后 reload,并重复同一请求验证。

官方参考:访问日志模块Real IP 模块命令行参数