nginx日志停止写入常见原因是文件描述符(fd)耗尽。需检查nginx进程fd使用量、系统限制(ulimit、fs.file-max)、配置中隐式增fd项(如多access_log、open_log_file_cache),并永久调整limitnofile或limits.conf,重启后验证生效。

当 Nginx 日志突然停止写入(如 access.log 或 error.log 不再更新),且无明显错误提示时,文件描述符(file descriptor, fd)耗尽是一个常见但易被忽略的原因。Nginx 每打开一个日志文件、连接、临时文件或 upstream 连接都会占用一个 fd,一旦超出系统限制,新日志就无法写入——表现为“静默丢日志”,error.log 本身也可能因 fd 不足而无法记录错误。
确认是否为 fd 耗尽导致的日志中断
直接检查 Nginx 进程当前使用的 fd 数量和系统限制:
- 查 Nginx 主进程 PID:
ps aux | grep "nginx: master",记下主进程 PID(如1234) - 统计其打开的 fd 数:
ls -l /proc/1234/fd/ | wc -l(注意:该值通常略高于实际活跃 fd,但可作参考) - 查看该进程的 fd 限制:
cat /proc/1234/limits | grep "Max open files",重点关注Soft Limit和Hard Limit - 对比系统默认限制:
ulimit -n(在启动 Nginx 的 shell 中执行);若输出是1024或4096,风险极高 - 检查内核级全局限制:
sysctl fs.file-max,确保远大于所有服务 fd 总和(如 >50 万)
检查 Nginx 配置中隐式增加 fd 消耗的设置
某些配置会显著提升 fd 占用,却不直观:
-
开启大量 access_log/error_log:每个
access_log /path/to/log main;语句都独占一个 fd;若在server或location块中重复定义,fd 数线性增长 -
使用 buffer 和 flush 参数不当:如
access_log /var/log/nginx/app.log main buffer=64k flush=5s;本身不增 fd,但 buffer 积压 + 多 worker 会导致更多临时写状态,间接加剧 fd 紧张(尤其配合open_log_file_cache) -
启用 open_log_file_cache:默认关闭;若开启(如
open_log_file_cache max=1000 inactive=20s min_uses=2 valid=1m;),会主动缓存日志 fd,虽提升性能,但也长期持有 fd,需纳入上限评估 -
log_format 中含变量触发子请求:极少见,但自定义 log_format 若含
$upstream_http_xxx等依赖 proxy_pass 响应头的变量,在未完成 upstream 交互前可能延迟释放 fd
永久调整 fd 限制(避免重启后失效)
仅改 ulimit -n 临时值无效,Nginx 启动后不会继承后续 shell 的 ulimit。必须在服务管理层面固化:
-
Systemd 环境(主流发行版):编辑
/etc/systemd/system/multi-user.target.wants/nginx.service或/usr/lib/systemd/system/nginx.service,在[Service]下添加:LimitNOFILE=65536
然后执行:systemctl daemon-reload && systemctl restart nginx -
SysVinit / 手动启停:修改 Nginx 启动脚本(如
/etc/init.d/nginx),在start()函数开头加入:ulimit -n 65536 -
全局用户限制(补充):编辑
/etc/security/limits.conf,添加:nginx soft nofile 65536nginx hard nofile 65536
(注意:此设置对 systemd 管理的服务默认不生效,需配合DefaultLimitNOFILE或上述 service 配置)
验证与辅助诊断技巧
调整后需交叉验证是否真正生效,并排除其他干扰:
- 重启 Nginx 后再次运行
cat /proc/PID/limits | grep "Max open files",确认 Soft/Hard Limit 已更新 - 模拟高并发请求,观察
ls -l /proc/PID/fd/ | wc -l是否持续逼近上限(如 >60000) - 用
lsof -p PID | grep log查看哪些日志文件被打开,确认无重复或残留句柄 - 临时关闭部分非核心日志(如注释掉某个
access_log),观察 fd 使用量是否明显下降,反向定位高消耗来源 - 检查
error.log中是否有open() "/path/to/log" failed (24: Too many open files)—— 这是最直接证据,但出现时往往已无法写入自身日志
不复杂但容易忽略:fd 问题常在流量增长、日志配置变更或系统升级后暴露,建议上线前用 ab 或 wrk 压测并监控 fd 使用曲线,把限制值设为预估峰值的 2–3 倍更稳妥。











