用pidstat监控nginx worker的fds字段变化节奏,结合lsof定期快照fd类型分布,可精准识别fd异常增长拐点:如压测30秒内翻倍、连接数未增但fd持续爬升,常指向access_log未缓冲、open_file_cache配置不当或unix socket连接未复用。

直接用 pidstat 和 lsof 实时追踪 Nginx 文件描述符(fd)增长,不是为了凑数,而是要抓准fd 消耗的节奏与异常拐点——比如压测刚开始 30 秒内 fd 翻倍、或连接数未增但 fd 持续爬升,往往意味着配置泄漏或连接未释放。
用 pidstat -r -p 监控 worker 进程 fd 实时变化
pidstat 本身不直接显示 fd 数,但它能持续输出每个 worker 的资源快照,配合 /proc/PID/status 中的 FDs 字段,可构造轻量实时曲线:
- 执行以下命令每秒采集一次所有 worker 的已用 fd 数(近似值,来自内核统计):
while true; do for pid in $(pgrep -f "nginx: worker process"); do fds=$(cat /proc/$pid/status 2>/dev/null | awk '/^FDs:/ {print $2}') echo "$(date +%s),worker-$pid,$fds" done | sort -t, -k2,2 sleep 1 done - 输出形如:
1726508301,worker-12345,8921,可重定向到文件,后续用gnuplot或 Excel 绘制时间序列图。 - 优势:开销极低,不依赖
lsof权限,适合长期挂起监控;FDs字段是内核维护的实时计数,比ls /proc/PID/fd | wc -l更快、更稳定。
用 lsof 定期快照,识别 fd 类型分布突变
lsof 耗资源,不适合高频调用,但每 5–10 秒执行一次,能帮你发现“谁在悄悄吃 fd”:
- 查看当前 fd 占比最高的类型(快速定位泄漏源):
lsof -p $(pgrep -f "nginx: worker" | head -n1) 2>/dev/null | \ awk '$5 ~ /^(REG|IPv[46]|sock)/ {type[$5]++} END {for (t in type) print t, type[t]}' | \ sort -k2 -nr | head -5常见输出示例:
IPv4 4217 REG 382 sock 156
- 若压测中
IPv4数随连接线性增长属正常;但若REG(普通文件)或sock(Unix 域套接字)数量异常上升,大概率是:-
access_log未启用 buffer/flush,每次写日志都新建 fd -
open_file_cache配置不当,频繁 open/close 静态文件 -
upstream使用了http://unix:/path.sock但未复用连接
-
关联 pidstat -u + ss -s 判断是否真瓶颈
fd 增长快 ≠ 系统要崩,得看它是否卡在关键路径上:
-
同时运行:
# CPU 和上下文切换(worker 是否忙于处理 fd 事件?) pidstat -u -p $(pgrep -f "nginx: worker") 1 # 全局 socket 统计(确认不是系统级耗尽) ss -s | grep -E "(inuse|orphan|tw)"
-
关键信号:
-
pidstat显示某 worker%CPU接近 100% 且cswch/s(每秒上下文切换)飙升 → epoll 循环被大量就绪事件拖住 -
ss -s中orphan(无归属连接)或tw(TIME-WAIT)远超预期 → 内核连接跟踪或端口复用配置不合理,间接推高 fd 压力
-
不复杂,但容易忽略:pidstat 提供的是进程维度的资源节奏,lsof 揭示的是 fd 的“身份构成”,两者交叉比对,才能把“fd 在涨”变成“fd 为什么涨、从哪涨、会不会断”。











