fs.file-max是系统级文件描述符总数上限,非单进程限制;需用sysctl持久化配置并验证内存是否足够,因每个fd约占1KB内核内存。

fs.file-max 是内核参数,不是 per-process 限制,设到数百万完全可行,但必须用 sysctl 持久化写入,且需确认内存是否撑得住 —— 每个打开的文件描述符约占用 1KB 内核内存,设成 500 万就得多预留 5GB 内核空间。
为什么 ulimit -n 改不了 fs.file-max
ulimit -n 只调整当前 shell 进程及其子进程的 per-process 打开文件数上限(即 RLIMIT_NOFILE),和 fs.file-max 完全无关。后者是系统级总配额,由内核维护,决定整个系统最多能分配多少 file struct 实例。
-
fs.file-max控制的是 系统全局可打开的文件描述符总数 -
ulimit -n控制的是 单个进程能持有的 fd 数量上限 - 两者不互相推导,也不自动同步;即使
fs.file-max设为 1000 万,ulimit -n默认仍可能是 1024
临时修改:用 sysctl -w 立即生效
运行时修改立刻起效,但重启后丢失:
sudo sysctl -w fs.file-max=5000000
验证是否成功:
cat /proc/sys/fs/file-max
注意:sysctl -w 要求你有 root 权限;若提示 permission denied,说明当前用户没被赋予 sysctl 权限(常见于容器或最小化系统)。
永久生效:写进 /etc/sysctl.conf 或 /etc/sysctl.d/
仅改运行时不够,必须落盘。推荐用独立配置文件,避免污染主配置:
echo 'fs.file-max = 5000000' | sudo tee /etc/sysctl.d/99-file-max.conf
然后加载:
sudo sysctl --system
这会重载所有 /etc/sysctl.d/*.conf 和 /etc/sysctl.conf。检查是否已应用:
sysctl fs.file-max
- 不要直接改
/etc/sysctl.conf—— 升级时可能被包管理器覆盖 - 文件名建议带数字前缀(如
99-),确保加载顺序靠后,避免被其他配置覆盖 - 设完别忘了
sysctl --system,只改文件不 reload 是不会生效的
内存够不够?别跳过这个检查
Linux 内核为每个打开的 fd 分配一个 struct file,典型大小约 0.8–1.2 KB。设 fs.file-max = 5000000,意味着内核需预留 ~5GB 连续 slab 内存。如果物理内存紧张或 slab 碎片多,系统启动时可能静默截断该值(dmesg 里能看到警告)。
查当前实际生效值和内存压力:
cat /proc/sys/fs/file-max<br>grep -i "file.*max" /proc/vmstat<br>dmesg | grep -i "file"
- 若
/proc/sys/fs/file-max显示的值明显低于你设置的(比如设了 500 万却只显示 1871116),大概率是内存不足触发了内核 fallback - 可通过
slabtop -o | grep filp观察filp(file pointer)缓存的实际占用 - 在低内存 VPS 或容器中,设太高反而导致
open()随机失败,错误是EMFILE(超出 per-process 限制)或ENFILE(超出fs.file-max总配额)
真正卡住人的地方往往不是怎么设,而是设完没验证、没看 dmesg、也没算内存账 —— 尤其在旧内核(如 4.x)或 cgroups v1 环境下,fs.file-max 的行为更隐蔽。











