error_log仅反映fd耗尽后果,需结合系统指标反向推断泄漏:重点识别accept() failed(24)是否集中于个别worker、是否与upstream超时或signal 9同步出现,并通过file-nr、ulimit、lsof及worker fd计数交叉验证。

直接看 error_log 本身并不能“监控”文件描述符泄漏,它只会在泄漏已造成后果时留下线索。真正有效的做法是:把 error_log 当作一个异常触发器,结合系统指标和日志模式,反向推断泄漏是否存在。
识别 error_log 中的关键泄漏信号
文件描述符泄漏不会在 error_log 里写“fd leak”,但会表现为以下几类高频、成簇、带时间规律的错误:
- accept() failed (24: Too many open files):这是最直接的表象。注意观察是否集中在个别 worker 进程(如 PID 12345 反复报错,而其他 worker 正常),这大概率指向该 worker 内部泄漏;若所有 worker 同步密集报错,则更可能是系统级或用户级限制被压穿。
- upstream timed out 或 connect() failed (24: Too many open files):当后端连接池无法新建 socket 时,也会触发这类错误,本质仍是 fd 不足,需与 accept 失败交叉比对时间戳。
- worker process X exited on signal 9:虽属内存问题,但 fd 泄漏常伴随内存增长(如未释放的连接结构体、缓存对象),二者常共存。若 signal 9 与 accept 失败在 dmesg 和 error_log 中时间高度重合,应同步排查 fd 和内存。
关联 error_log 时间戳做横向验证
单看一条日志没意义,关键在于“时间+进程+频率”三维锁定:
- 用
grep "Too many open files" /var/log/nginx/error.log | head -20提取最近报错,记录最早/最晚时间及涉及的 worker PID。 - 对照执行
ps -eo pid,comm,lstart,etime --sort=-etime | grep nginx,确认这些 PID 是否为长期运行的 worker(而非刚 fork 的)。 - 再查对应 PID 的 fd 数:
ls /proc/<pid>/fd 2>/dev/null | wc -l</pid>。若该值持续 >5000 且随运行时间上升,基本坐实泄漏。
配置 error_log 辅助定位(非监控,而是增强线索)
默认 warn 级别信息有限,临时调高可暴露更多上下文:
- 在 nginx.conf 的 http 块中添加:
error_log /var/log/nginx/error.log debug; - 重启后,留意 debug 日志中高频出现的
http cleanup add、event timer add、ngx_http_upstream_connect等条目——若某类事件数量远超请求量(如每 1 次请求却触发 10 次 timer add),说明资源注册未匹配释放。 - 注意:debug 日志体积大,仅用于短时诊断,定位后务必切回 warn 或 error。
必须配合的系统级检查项
error_log 是“症状”,不是“病因”。以下命令必须同步执行,才能闭环判断:
- 查系统总量瓶颈:
cat /proc/sys/fs/file-nr(第一列 ≥ 第三列 × 0.9 即危险) - 查 Nginx 用户限制:
sudo -u nginx bash -c 'ulimit -n'(确认是否低于 worker_rlimit_nofile) - 查当前各 worker fd 分布:
ps aux | grep 'nginx: worker' | awk '{print $2}' | xargs -I{} sh -c 'echo "PID {}"; ls /proc/{}/fd 2>/dev/null | wc -l' - 查泄漏源头:
lsof -p <nginx_worker_pid> | awk '{print $5}' | sort | uniq -c | sort -nr | head -5</nginx_worker_pid>(看是不是大量 IPv4、pipe 或 anon_inode)


















