必须在具体匹配路径的location块内写access_log off;才真正生效,因nginx日志开关是“就近覆盖”而非“全局屏蔽”,子location会继承上级配置但不自动关闭日志。

直接在 location 块里写 access_log off; 才真正生效
很多人在 server 或 http 块里加了 access_log off;,结果静态资源还在狂写日志——因为子 location 会继承上级配置,但只要它自己没显式关掉,就仍会记录。Nginx 的日志开关是“就近覆盖”,不是“全局屏蔽”。
必须把 access_log off; 放进具体匹配路径的 location 块内部,比如:
location ~* \.(js|css|png|jpg|gif|ico|woff2|svg|webp)$ {
access_log off;
expires 1y;
}
-
~*是大小写不敏感正则,适合后缀匹配;若用前缀(如/static/),优先选^~ /static/,性能更好 - 这个
location块得写在location /或proxy_pass规则之前,否则可能被兜底规则捕获并记日志 - 别用
if ($uri ~* \.js$) { access_log off; }——if在location外不支持access_log指令,语法错误且无效
用 map + access_log if= 只记异常响应
如果不能完全关日志(比如审计要求保留部分请求),最省空间的方式是:只记录非 200 和非 304 的响应。这两类占全部日志的 85%–95%,尤其在 CDN 回源或静态资源场景下。
在 http 块中定义映射:
map $status $log_abnormal {
~^[23]0[04] 0;
default 1;
}
然后在 server 或 location 中启用条件日志:
通过 yarn-threads-cli 与 Threads(Meta)交互。当用户想要阅读首页动态、点赞、收藏的帖子或特定帖子时使用;查看...
access_log /var/log/nginx/abnormal.log main if=$log_abnormal;
- 该功能要求 Nginx ≥ 1.7.0,且
ngx_http_map_module已启用(默认编译进核心) - 别试图用
log_if $status != 200—— Nginx 不支持这种写法,map是唯一可靠方式 - 配合关闭静态资源日志(上一节方法),能再砍掉 30%+ 的剩余日志量
健康检查和探针路径必须单独关日志
像 /healthz、/ping、/metrics 这类路径,每秒可能被 K8s 或监控系统调用数十次,但内容固定、无业务价值,是最该关日志的“高频低信息密度”目标。
精确匹配性能最好:
location = /healthz {
access_log off;
return 200 "OK";
}
-
location = /path是精确匹配,比正则快,也避免误伤其他类似路径 - 如果路径带参数(如
/healthz?full=1),Nginx 默认忽略 query string,仍能命中;如需区分,得用if ($args ~ full)配合内部重写,但一般没必要 - 别用
access_log /dev/null;替代access_log off;—— 前者仍打开文件句柄、执行格式化、触发 write 系统调用,后者彻底跳过整个日志流程
验证是否真的不写了,别信配置 reload 就完事
改完配置 nginx -t && nginx -s reload 后,必须手动验证。很多失效是因为 location 顺序错、正则写漏、或被 proxy_pass 拦截导致根本没进目标块。
- 用
tail -f /var/log/nginx/access.log,另起终端发请求:curl -I https://example.com/app.js或curl https://example.com/healthz,看日志是否新增 - 检查是否真进了目标
location:临时加个add_header X-Location-Match "static";,用curl -I看响应头 - 若还写日志,用
nginx -T | grep -A5 -B5 'access_log'看最终生效的配置位置,常有隐藏的 include 文件覆盖了你的设置
真正容易被忽略的是:location 的匹配优先级和嵌套关系。一个看似正确的 access_log off;,只要没落在实际处理请求的那个 location 块里,就等于没写。










