生产环境Nginx文件描述符不足会导致连接拒绝等故障,需验证系统级fs.file-max、nginx用户ulimit及worker进程实际limits三层一致性,并通过脚本巡检、告警与自动修复(如注入LimitNOFILE并重启)。

生产环境 Nginx 文件描述符(file descriptor, FD)不足会导致“Too many open files”错误、连接拒绝、请求超时甚至服务中断。单纯设置一次 ulimit 或内核参数远远不够——配置可能被覆盖、服务重启后未生效、worker 进程实际继承值与预期不符。真正有效的巡检,必须验证“系统限制→用户限制→Nginx进程实际可用值”三层一致性,并在异常时告警或自动修复。
确认当前系统级文件描述符上限
巡检第一步是验证操作系统是否已按高并发场景调优。关键指标是 fs.file-max 和 nofile 限制:
- 执行
sysctl fs.file-max,生产建议 ≥ 2097152(200万) - 检查
/etc/sysctl.d/*.conf中是否持久化配置(如fs.file-max = 2097152),避免仅用临时命令 - 确认
ulimit -Hn(硬限制)和ulimit -Sn(软限制)对 nginx 用户生效,推荐设为一致值(如 1048576)
验证 Nginx worker 进程实际继承的 fd 限制
即使系统和用户层配置正确,Nginx 启动方式(systemd / 直接启动)可能导致 worker 进程未继承预期限制。需直接读取运行中进程的 limits:
- 获取任一 worker PID:
pgrep -f "nginx: worker" | head -n1 - 查看其 limits:
cat /proc/<PID>/limits | grep "Max open files" - 输出应类似:
Max open files 1048576 1048576 files(软硬限制一致且达标) - 若显示 1024 或 4096,说明 systemd service 配置缺失
LimitNOFILE=,或未重载配置
编写可落地的巡检脚本(含自动修复逻辑)
以下脚本保存为 /usr/local/bin/nginx-fd-check.sh,具备检测、比对、告警、修复能力:
#!/bin/bash
# 检查目标:系统全局上限、nginx用户ulimit、worker进程实际限制
SYS_LIMIT=$(sysctl -n fs.file-max 2>/dev/null)
USR_SOFT=$(su - nginx -c 'ulimit -Sn' 2>/dev/null)
USR_HARD=$(su - nginx -c 'ulimit -Hn' 2>/dev/null)
WORKER_PID=$(pgrep -f "nginx: worker" | head -n1)
<p>if [[ -z "$WORKER_PID" ]]; then
echo "[ERROR] No nginx worker process found"
exit 1
fi</p><p>WORKER_LIMIT=$(cat "/proc/$WORKER_PID/limits" 2>/dev/null | awk '/Max open files/{print $4}')
THRESHOLD=1048576</p><p>if [[ "$SYS_LIMIT" -lt "$THRESHOLD" ]] || [[ "$USR_SOFT" -lt "$THRESHOLD" ]] || [[ "$USR_HARD" -lt "$THRESHOLD" ]] || [[ "$WORKER_LIMIT" -lt "$THRESHOLD" ]]; then
echo "[ALERT] FD limit too low: sys=$SYS_LIMIT, user=(s:$USR_SOFT/h:$USR_HARD), worker=$WORKER_LIMIT"</p><h1>可选:自动写入 systemd 配置并重载(需 root 权限)</h1><p>if [[ "$(id -u)" == "0" ]] && [[ -f "/usr/lib/systemd/system/nginx.service" ]]; then
if ! grep -q "LimitNOFILE=" /usr/lib/systemd/system/nginx.service; then
sed -i '/[Service]/a LimitNOFILE=1048576' /usr/lib/systemd/system/nginx.service
systemctl daemon-reload
systemctl restart nginx
echo "[INFO] nginx service updated and restarted"
fi
fi
exit 2
else
echo "[OK] All FD limits meet threshold ($THRESHOLD)"
fi
集成到定时任务与可观测体系
脚本需定期执行并纳入统一监控链路:
- 添加 crontab(每 6 小时检查一次):
0 */6 * * * /usr/local/bin/nginx-fd-check.sh >> /var/log/nginx-fd-check.log 2>&1 - 日志输出统一为 JSON 格式(可用 jq 或简单 sed 转换),便于 ELK/Prometheus 抓取
- 关键字段示例:
{"time":"$(date -Iseconds)","host":"$(hostname)","status":"OK","sys_limit":2097152,"worker_limit":1048576} - 配合 Prometheus + node_exporter,可采集
process_max_fds和process_open_fds指标,绘制使用率趋势图


















