访问日志与错误日志
日志是 Nginx 排错的“第一现场”。一个优秀的日志策略既能完整保留请求上下文,又不会撑爆磁盘。下面从格式定制、存储轮转、错误分级三个维度详细讲解。
一、日志格式定制(log_format)
默认的 combined 格式包含基本字段,但往往不够用。你需要通过自定义 log_format 组合变量,记录下真实客户端 IP、上游响应时间、负载均衡节点等关键信息。
1. 语法与使用
http {
log_format main_ext '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'rt=$request_time uct=$upstream_connect_time '
'uht=$upstream_header_time urt=$upstream_response_time '
'upstream_addr=$upstream_addr';
access_log /var/log/nginx/access.log main_ext buffer=64k flush=5s;
}
log_format必须在http块中定义,之后在access_log指令中引用指定格式。- 每个变量之间有空格,末尾可用
\换行续写。
2. 常用变量速查
| 变量名 | 含义 | 注意事项 |
|---|---|---|
$remote_addr | 直接连接的客户端 IP(可能是代理服务器的 IP) | 要获取真实 IP,需配合 real_ip_header 或记录 $http_x_forwarded_for |
$http_x_forwarded_for | 代理链中原始客户端的 IP 列表,通常取第一个 | 该头可被客户端伪造,须在可信代理处清除并追加 |
$request | 原始的请求行,如 GET /index.html HTTP/1.1 | 包含方法和协议版本 |
$status | 响应状态码 | |
$body_bytes_sent | 发送给客户端的 Body 字节数,不含响应头 | |
$request_time | 从接收客户端第一个字节到发送完最后一个字节的总耗时(秒) | 包含网络和 Nginx 内部处理时间 |
$upstream_connect_time | 与上游建立连接耗时(秒) | 需要反向代理模块 |
$upstream_header_time | 从上游接收到响应头的耗时(秒) | 同上 |
$upstream_response_time | 从上游接收完整响应的总耗时(秒) | 同上 |
$upstream_addr | 上游服务器的地址和端口 | 记录请求实际发给了哪个后端,用于排查负载不均 |
$upstream_status | 上游返回的状态码 | 判断后端是否健康 |
$http_referer | 请求头 Referer | |
$http_user_agent | 请求头 User-Agent | |
$ssl_cipher / $ssl_protocol | 当前连接使用的加密套件和协议 | 排查 SSL 相关问题 |
记录真实 IP 的最佳实践:在反向代理处设置 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 和 proxy_set_header X-Real-IP $remote_addr;,然后在日志中记录 $http_x_forwarded_for 或使用 real_ip_header 指令覆盖 $remote_addr。这样即使经过多层代理,也能找到原始客户端。
3. 示例:排查性能瓶颈的增强日志
log_format perf '$remote_addr [$time_local] '
'"$request" $status $body_bytes_sent '
'ref="$http_referer" '
'rt=$request_time '
'ups_resp_time=$upstream_response_time '
'ups_addr=$upstream_addr '
'ups_status=$upstream_status';
通过 rt 与 ups_resp_time 的对比,可以快速判断耗时究竟在 Nginx 本身还是上游服务。
二、日志路径与轮转
1. access_log 与 error_log 配置
访问日志 access_log
可用在 http, server, location 上下文,支持以下功能:
access_log /var/log/nginx/access.log main_ext; # 基本用法
access_log /var/log/nginx/access.log main_ext buffer=64k flush=5s; # 缓冲与刷新
access_log /var/log/nginx/access.log main_ext gzip=9; # gzip 压缩(需编译支持)
access_log off; # 关闭日志(提升性能)
buffer:日志先写入内存缓冲区,达到大小或到达flush时间后才刷入磁盘,减少 I/O。gzip:使用 zlib 动态压缩,适合大流量站点,注意对 CPU 的影响。- 多日志:可以用不同格式记录不同类型的请求,例如限制日志只记录 5xx 错误:
nginx
map $status $loggable { ~^[5] 1; default 0; } access_log /var/log/nginx/error_traffic.log main_ext if=$loggable;
错误日志 error_log
记录服务器运行期间的错误、警告及调试信息,支持 main, http, server, location 多级覆盖。
error_log /var/log/nginx/error.log warn;
- 支持输出到文件、stderr 或 syslog。
- 级别越宽泛(如
debug),信息越多,但性能开销越大。
2. 日志轮转:防止磁盘被吃满
Nginx 本身不会自动切割日志,需借助外部工具。
(1) 使用 logrotate
这是 Linux 下最标准的方式。创建一个配置文件 /etc/logrotate.d/nginx:
/var/log/nginx/*.log {
daily # 每天切割
missingok # 日志文件不存在时不报错
rotate 30 # 保留 30 份
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
}
关键点:
postrotate中的kill -USR1通知 Nginx 重新打开日志文件。Nginx 收到USR1信号后,会关闭并重新打开所有日志文件,避免写入被删除的文件描述符。- 可以通过执行
logrotate -d /etc/logrotate.d/nginx进行调试测试。 - 实际执行:
logrotate -f /etc/logrotate.d/nginx可强制立即切割一次。
(2) 使用 cron 脚本(不推荐,除非无 logrotate)
可以写一个简单的 bash 脚本,利用 mv 和 kill -USR1,但需要处理好竞争和清空问题,logrotate 更可靠。
3. 日志管理高级建议
- 搭配 PID 文件:确保
pid /run/nginx.pid;路径正确。 - 如果 Nginx 运行在容器中,通常将日志重定向到标准输出(
/dev/stdout、/dev/stderr),由容器日志驱动统一收集和轮转。
三、错误日志级别
Nginx 错误日志级别从低到高分为:debug, info, notice, warn, error, crit, alert, emerg。设置越高,记录越少。
| 级别 | 说明 |
|---|---|
debug | 最详细,包含内部处理流程、正则匹配等,用于开发调试 |
info | 一般信息,如配置加载、worker 进程启动等 |
notice | 需要注意但非错误的事件,如重载配置、优雅关闭 |
warn | 警告信息,如客户端超时、某些限制值被触及 |
error | 处理请求时的错误,如 500 错误、上游连接失败、SSL 握手失败 |
crit | 较高严重级问题,如 socket 创建失败、共享内存不足 |
alert | 需要立即动作的严重问题 |
emerg | 系统级不可用,如内存分配失败 |
配置示例
error_log /var/log/nginx/error.log warn; # 生产环境推荐
部分模块的调试信息(如 rewrite)需在编译时指定 --with-debug,并在运行时使用 error_log 设置 debug 级别配合 debug_connection 过滤。
何时开启 debug 日志?
仅在以下场景短暂启用,且最好针对特定 IP:
- 复杂的
rewrite或location不按预期匹配,需要知道内部跳转细节。 - 排查反向代理缓存不生效的问题。
- SSL 握手失败,需要了解具体算法协商过程。
- 第三方模块的行为异常。
开启方法(假设已经编译了 debug 支持):
error_log /var/log/nginx/debug.log debug; # 全局开启,极耗性能,不推荐
# 更好的方式:仅记录特定客户端的调试信息
events {
debug_connection 192.168.1.100; # 仅对该 IP 输出 debug 日志
debug_connection 10.0.0.0/8;
}
debug_connection需配合error_log级别设为debug起效。- 调试结束后务必立即关闭或恢复为
warn,并清理 debug 日志文件,否则磁盘和 CPU 会迅速耗尽。
把格式设得恰到好处,将轮转配置到位,并熟练掌握错误日志级别的切换,你的 Nginx 就能始终保持“透明”——任何请求的来龙去脉、任何错误的蛛丝马迹都有据可查。这既是运维的基本功,也是快速止损的关键能力。
参考文献
相关文章
安全基础
Nginx 作为流量的总入口,安全配置是防线第一关。以下从六个基础维度加固你的服务,既实用又立竿见影。
配置文件结构与语法
下面我们深入到 Nginx 的配置核心——配置文件的结构、语法和变量系统。这一部分是你驾驭 Nginx 的“语法手册”。
核心模块与常见指令详解
深入 Nginx 的指令层,是配置落地的关键。下面按功能模块拆解,每个指令都说明含义、语法、典型示例,并点出极易踩坑的地方。
Nginx 核心概念
Nginx 是一款高性能的 HTTP 和反向代理服务器。学习路径见 运维导读。它的强大并发能力与灵活的扩展性根植于少数几个核心设计。理解这些底层原理,后续的配置、调优和排障都会变得通透。
常见故障排查思路
故障排查的关键是快速定位,而非盲目重试。下面按最常见的五种现象归类,每一种都给出清晰的排查路径和解决思路。
性能调优基础
性能调优的目标是:用有限的资源,支撑更高的并发、更快的响应、更稳的服务。下面按优化维度,逐一拆解原理和配置要诀。
Series
nginx
4 / 7