nginx日志切割不支持正则提取,需用grep -e等外部工具在logrotate后处理中匹配“upstream timed out”等错误并归档;error_log不可在nginx配置中正则路由,因格式固定且无过滤重定向机制。

在 Nginx 中,日志切割本身不支持正则表达式提取——logrotate 或系统定时任务只负责按时间/大小切分文件,不解析内容;真正实现“精准提取特定错误日志”需分两步:先用 grep + 正则 过滤出目标错误行,再归档到独立文件。核心在于把“匹配逻辑”从 Nginx 配置移到日志后处理流程中。
为什么不能在 Nginx 配置里直接正则分割?
Nginx 的 access_log 和 error_log 指令不接受正则条件路由;map 模块可配合变量做条件日志,但仅适用于 access_log(且依赖请求变量,无法匹配 error_log 中的报错文本)。error_log 是由 Nginx 内部直接写入的,格式固定、不可过滤重定向。
所以,想提取类似 “upstream timed out”、“502 Bad Gateway”、“Connection refused” 等特定错误,必须在日志生成后,用外部工具处理。
用 grep -E 提取带时间戳的错误行(推荐方案)
假设原始 error 日志路径为 /var/log/nginx/error.log,每天切割后保留为 error.log.20241025,可用以下命令精准提取:
grep -E "(upstream timed out|Connection refused|502.*Bad Gateway|connect\(\) failed)" /var/log/nginx/error.log.20241025 > /var/log/nginx/errors_5xx_upstream_20241025.log- 加
-o只输出匹配部分(不常用),加-n带行号便于追溯,加--color=always方便肉眼确认 - 注意转义:正则中点号
.要写成\.(如匹配502\.Bad),括号用反斜杠转义或改用[[:space:]]匹配空白更稳妥
结合 logrotate 实现自动归档(关键配置示例)
在 /etc/logrotate.d/nginx 中,利用 postrotate 钩子执行提取脚本:
- 确保 logrotate 切割后触发脚本:
/var/log/nginx/error.log {<br> daily<br> missingok<br> rotate 30<br> compress<br> delaycompress<br> notifempty<br> create 0644 www-data www-data<br> sharedscripts<br> postrotate<br> if [ -f /var/run/nginx.pid ]; then<br> kill -USR1 `cat /var/run/nginx.pid`<br> fi<br> /usr/local/bin/extract-nginx-errors.sh<br> endscript<br> } -
extract-nginx-errors.sh内容示例:#!/bin/bash<br> LOG_DATE=$(date -d 'yesterday' +\%Y\%m\%d)<br> grep -E "(50[2-4]|upstream.*timeout|refused|no live upstream)" /var/log/nginx/error.log.$LOG_DATE >> /var/log/nginx/summary_errors.log<br> gzip /var/log/nginx/error.log.$LOG_DATE
进阶:用 awk 按错误类型分目录归档
若需将不同错误存入不同目录(如 /var/log/nginx/errors/timeout/、/var/log/nginx/errors/connect/),可用 awk 分流:
awk '{<br> if (/upstream timed out/) { print > "/var/log/nginx/errors/timeout/error_" strftime("%Y%m%d") ".log" }<br> else if (/Connection refused/) { print > "/var/log/nginx/errors/connect/error_" strftime("%Y%m%d") ".log" }<br> else if (/502|503|504/) { print > "/var/log/nginx/errors/5xx/error_" strftime("%Y%m%d") ".log" }<br> }' /var/log/nginx/error.log.20241025- 注意:gawk 支持
strftime(),mawk 不支持,生产环境建议用 gawk 并显式指定gawk -f script.awk
不复杂但容易忽略:正则要覆盖常见变体(比如 “timeout” 可能是 “time out”、“timed out”、“timeout while reading response”),建议先用 zcat error.log.20241025.gz | head -1000 | grep -i timeout 采样真实日志再调优正则。归档路径要有写权限,脚本需 chmod +x,并测试单次执行是否成功。











