应先看/proc/sys/fs/file-nr第二列是否≥第三列(file-max),若成立则为系统级耗尽;否则必是某进程ulimit软限制导致,需查/proc/[pid]/limits并验证pam_limits.so加载及systemd服务limitnofile配置。

直接看 /proc/sys/fs/file-nr 第二列,大于 /proc/sys/fs/file-max 就是系统级耗尽;否则一定是某个进程的 ulimit 软限制卡住了。
怎么看是系统级还是进程级瓶颈
系统级耗尽极少见,但一旦发生,连 ls、ps 都会失败——因为它们也要打开文件。先快速判断:
- 执行
cat /proc/sys/fs/file-nr,输出三列数字,**第二列是已分配未释放的句柄数**; - 执行
cat /proc/sys/fs/file-max,这是内核允许的全局上限; - 如果第二列 ≥ 第三列(即接近或超过
file-max),说明真·系统级打满了; - 否则,问题一定出在某个进程自己的
ulimit -n限制上,哪怕file-max是 100 万也没用。
怎么查哪个进程在狂开句柄
别盲目 lsof | wc -l,那会卡死。用更轻量的方式定位高消耗进程:
yuanfang-skills 的共享设计系统,提供 token CSS 变量、12+ 主题以及可复用的布局类型 HTML 块,供 yuanfang-html-image(以及 fu...)使用。
- 执行
lsof -n -S 1 | awk '{print $2}' | sort | uniq -c | sort -nr | head -10(加-S 1避免 DNS 反查拖慢); - 对疑似进程,用
ls -1 /proc/<code>PID/fd/ 2>/dev/null | wc -l 精确统计(比lsof -p PID | wc -l更快更稳); - 注意:Java 进程常因
inotify监控目录暴增句柄,lsof -p PID | grep inotify可验证; - Python 或 Node.js 若用了大量临时文件或未关闭的
socket,lsof -p PID | grep -E "(REG|IPv|sock)"能区分类型。
为什么改了 /etc/security/limits.conf 还不生效
这是最常踩的坑:配置写了,但根本没加载。关键检查点:
- 确认
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/login(RHEL/CentOS)里有session required pam_limits.so; -
systemd 服务默认**忽略**
limits.conf,必须单独配LimitNOFILE=65536到.service的[Service]段; - 改完 limits.conf 后,**必须重新登录用户**(不是
source ~/.bashrc,也不是su - user); - 验证是否生效:切换到目标用户后,运行
sh -c 'echo $$; ulimit -n',再cat /proc/$(echo $$)/limits | grep "Max open files"对照。
为什么 ulimit -n 65536 有时会失败
不是权限不够,就是硬限制(hard limit)挡着了:
- 执行
ulimit -Hn查硬限制,若低于 65536,得先提硬限:ulimit -Hn 65536(需 root 或 CAP_SYS_RESOURCE); - 非 root 用户无法把软限制设得比硬限制高,所以
ulimit -n失败时,先看ulimit -Hn; - 某些容器环境(如 Docker)会继承宿主的
ulimit,但容器启动时没传--ulimit nofile=65536:65536,容器内依然卡在 1024; - 硬限制本身受内核参数
fs.nr_open约束,若它比你要设的 hard limit 小,sysctl -w fs.nr_open=1048576才能放开。
真正麻烦的从来不是改数字,而是硬限制和 fs.nr_open 的隐式依赖关系——改错一个,整个登录链就断掉。动手前先记下原始值,别图省事直接 echo 覆盖。










