Nginx默认combined日志含7个内置变量:$remote_addr(原始客户端IP,经代理后为上一跳地址)、$request(解码后的完整请求行)、$status(最终HTTP状态码)、$body_bytes_sent(响应体字节数)、$http_referer(可能为空)、$http_user_agent(可伪造)、$time_local(本地时区时间)。

默认日志格式(即 combined)是 Nginx 开箱即用的日志样式,它不依赖显式 log_format 定义,但背后已固化一组关键内置变量。理解每个变量的实际来源、取值逻辑和常见陷阱,比单纯记住格式更重要。
默认格式长什么样?
Nginx 内置的 combined 格式等价于:
log_format combined '$remote_addr - $remote_user [$time_local] "$request" '$status $body_bytes_sent "$http_referer" "$http_user_agent"'
它共含 7 个核心字段,顺序固定,每项都对应一个动态生成的内置变量,而非静态字符串。
$remote_addr:你以为的“客户端IP”,其实常是代理地址
该变量取自 TCP 连接的远端 IP,**未经任何代理链解析**。直连时确实是真实用户 IP;但经过 CDN、LB 或反向代理(如另一层 Nginx)后,它往往变成上一跳代理的内网 IP(如 10.0.1.5),而非用户真实出口 IP。
要获取真实 IP,需配合 $http_x_forwarded_for 并在上游明确设置 proxy_set_header X-Forwarded-For $remote_addr,再通过逻辑提取最左非私有地址。
$request:完整请求行,但不含响应头或 body
它的值形如 "GET /api/v1/users?id=123 HTTP/1.1",包含三部分:
- HTTP 方法(
GET、POST等) - 规范化后的请求 URI(
/api/v1/users?id=123),已解码、去多余斜杠,但保留原始查询参数 - 协议版本(
HTTP/1.1或HTTP/2)
注意:$request 不等于 $uri(只含路径)或 $args(只含参数),也不包含请求体内容或响应信息。
$status 和 $body_bytes_sent:响应层面的关键指标
$status 是 Nginx 最终返回给客户端的 HTTP 状态码,例如 200、404、502。它反映的是 Nginx 自身决策结果——可能是后端返回的,也可能是 Nginx 自己生成的(如配置了 error_page 404 /404.html 后,状态仍是 404)。
$body_bytes_sent 表示实际发送给客户端的响应体字节数(不含响应头)。若响应被截断、连接中断或使用了 chunked 编码且未完成,该值可能小于预期。它与 $bytes_sent 的区别在于:后者包含响应头大小,而日志中默认用的是前者。
$http_referer 和 $http_user_agent:来自请求头,但可能为空或伪造
这两个变量直接映射客户端发起请求时携带的 Referer 和 User-Agent 请求头。
-
$http_referer在直接输入 URL、书签访问或 HTTPS 页面跳转到 HTTP 页面时,通常为空字符串(-) -
$http_user_agent可被任意修改,不能用于安全判断;但对统计浏览器分布、爬虫识别仍有基础价值 - 变量名中的下划线是固定规则:
Referer → http_referer,User-Agent → http_user_agent,所有HTTP_头都按此转换
$time_local:本地时区时间,非 UTC
格式为 [10/May/2026:01:10:22 +0800],其中时区偏移量(+0800)由系统本地时区决定,不是 Nginx 配置项。它在每条日志生成时实时计算,精度到秒,不包含毫秒。
若需统一 UTC 时间便于日志聚合分析,应改用 $time_iso8601(格式如 2026-05-09T17:10:22+00:00)并确保系统时区设为 UTC,或在日志收集端做时区转换。











