最权威的系统级文件描述符上限是/proc/sys/fs/file-max的实时值,/proc/sys/fs/file-nr第一列显示当前已分配总数,接近第三列即达上限;进程真实限制须查/proc/[pid]/limits,systemd服务需在[Service]段设LimitNOFILE并daemon-reload。

看系统级上限:直接读 /proc/sys/fs/file-max
这才是最权威的实时值,不是配置文件里写的、也不是 sysctl fs.file-max 缓存的。内核运行时就靠它管总数,比如输出 2097152,意思就是全系统最多能分配这么多 fd。别信 /etc/sysctl.conf 里有没有那行——没执行 sysctl --system,改了也白搭。
查当前真实用量:/proc/sys/fs/file-nr 的第一列才是关键
执行 cat /proc/sys/fs/file-nr 得到类似 12480 0 2097152 的三列数字:
- 第一列
12480:已分配出去的 fd 总数(含已关闭但未回收的),≈ 实际占用量 - 第二列通常为
0,现代内核基本不保留“预分配但未用”的池子 - 第三列等于
file-max,是硬上限
如果第一列接近第三列(比如差不到 5%),说明系统级快满了,调单个进程的限制没用。
验证具体进程的软硬限制:必须看 /proc/[pid]/limits
ulimit -n 只反映当前 shell,对 systemd 服务完全无效。真正生效的限制藏在进程自己的 limits 文件里:
- 先找到 pid:
pgrep nginx或systemctl show nginx --property=MainPID - 再查限制:
cat /proc/$(pgrep nginx | head -n1)/limits | grep "Max open files" - 输出如
Max open files 65536 65536 files,左边是 soft,右边是 hard
如果这里还是 1024,哪怕你改了 /etc/security/limits.conf,也说明 systemd 没加载你的配置。
systemd 服务改 limit 容易漏掉的三个地方
写 LimitNOFILE=65536 不等于生效:
- 必须放在 unit 文件的
[Service]段下,写在[Unit]或[Install]里无效 - 改完要
systemctl daemon-reload,否则 reload service 也不起作用 - 硬限制不能超过内核的
fs.nr_open(默认1048576),否则服务启动失败且无明确报错
最终是否落地,只认 /proc/[pid]/limits 里的数字——其他所有配置都是中间步骤,这行才是终点。


















