网站运行一段时间后开始无法建立新连接,应用日志出现 Too many open files,重启服务又能恢复。这个现象很容易被理解成服务器的文件数量太多,实际触发的是进程或系统无法再分配文件描述符。
网络Socket、日志、管道、监听端口和普通文件都会占用文件描述符。重启只会关闭现有描述符,它既不能证明上限太低,也不能排除程序持续泄漏。

先锁定报错进程和时间
从应用、反向代理和系统日志记录首次报错时间、服务名与PID:
systemctl status app.service
journalctl -u app.service --since '30 minutes ago'
pidof app-binary
服务可能已经自动重启,当前PID不一定是报错时的进程。结合systemd重启记录、监控和应用实例标识,避免拿新进程的低占用解释旧进程的失败。
同一服务器上的Nginx、数据库和应用可能分别设置限制。哪一个日志明确返回EMFILE或Too many open files,后续证据就应围绕哪个进程收集。
比较当前占用和进程上限
对目标PID读取打开描述符数量与限制:
sudo sh -c 'ls -1 /proc/PID/fd | wc -l'
cat /proc/PID/limits | grep -i 'open files'
把PID替换为真实数字。数量逼近 Max open files 的软限制,能够说明本次失败首先发生在进程级边界;占用很低却报错,则要检查是否查错进程、进程已经重启,或错误实际来自另一个组件。
不要用 lsof | wc -l 直接当作全系统准确总数。lsof输出可能包含重复项,遍历高负载服务器也有成本。/proc/PID/fd 更适合确认单个进程当前占用。
文件描述符都被什么占用
先对目标进程做分类,而不是只看一个总数:
sudo lsof -nP -p PID
sudo lsof -nP -p PID | awk 'NR>1 {print $5}' | sort | uniq -c | sort -nr | head
sudo ss -tanp
大量TCP连接可能来自真实并发、连接未关闭或异常流量;大量重复日志、管道和已删除文件,则指向不同的程序路径。短时间抓取两到三次,观察某一类型是否只增不减,比单张截图更能判断泄漏。
应用应记录连接池、活跃请求、队列和打开文件的业务指标。只看到Socket很多,还需要结合连接状态、来源和业务并发判断它们是不是异常。
区分进程限制和系统级上限
系统级文件句柄状态可以从内核接口读取:
cat /proc/sys/fs/file-nr
sysctl fs.file-max
Linux内核文档说明,file-nr 展示已分配文件句柄、未使用句柄以及最大值;较新的Linux通常把中间的未使用值报告为0。系统级已分配值接近最大值时,才需要把排查范围扩展到所有进程。
进程先触发自己的软限制时,盲目调高 fs.file-max 不会改变该进程边界。反过来,只提高单个服务限制,也无法解决全机被多个进程共同耗尽的情况。
systemd服务不要只改当前Shell的ulimit
在SSH终端执行 ulimit -n,看到的是当前Shell及其子进程的限制,不代表systemd启动的服务。先读取服务实际属性和单元配置:
systemctl show app.service -p LimitNOFILE
systemctl cat app.service
需要调整时,使用覆盖配置而不是直接修改发行版自带单元文件:
[Service]
LimitNOFILE=65536
保存后执行 systemctl daemon-reload 并在维护窗口重启目标服务,再从新PID的 /proc/PID/limits 验证。数值应根据业务并发、程序能力和系统容量确定,不是越大越安全。
先修泄漏还是先提高限制
稳定并发确实增长、描述符会正常回收,并且当前上限低于合理容量时,可以评估提高限制。占用随时间持续单向增长,重启后按相似斜率再次逼近上限,则更接近程序泄漏或连接管理错误。
紧急情况下适度提高限制能争取排查时间,但必须同步设置监控和回滚条件。无限放大上限可能把原本局限在单个服务的问题扩散为系统句柄、内存或连接资源耗尽。
旧服务器长期叠加多个服务且无法判断是谁增长时,可以在 萤光云 创建相近规格复现,也可以使用按小时计费的 LightNode 建立短期对照环境。对照时保持相同应用版本、并发模型和观测时长,不能只比较刚启动时的文件描述符数量。
建立可复现的验收标准
修复后确认新进程的软硬限制与设计一致,在真实高峰或受控压测中记录描述符数量曲线。并发回落后,Socket和文件占用应回到稳定区间,不再持续逼近上限。
应用、Nginx和数据库日志不再出现EMFILE或Too many open files,新连接成功率与响应时间恢复。系统级 file-nr 也没有异常增长。
至少观察一个完整业务周期,并验证服务重启后LimitNOFILE仍然生效。限制已提高、增长曲线稳定、泄漏路径得到修复三项同时满足,才算排查闭环。


