linux文件描述符配额有四层独立限制:1.进程级(ulimit,仅当前会话生效);2.用户级(/etc/security/limits.conf,pam登录后生效);3.systemd服务级(unit中limitnofile,需daemon-reload重启);4.系统级(fs.file-max,内核全局上限)。

Linux 中配置文件描述符(file descriptor, fd)配额上限,不能只改一个地方——它有四层独立限制,漏掉任何一层都可能让服务继续报 Too many open files。关键不是“设多大”,而是“在哪设、对谁生效、要不要重启”。
1. 进程级软/硬限制(ulimit,当前会话有效)
这是最直接、也最容易误用的一层。它只影响当前 shell 及其后续 fork 的进程,退出终端即失效。
- 查看当前值:
ulimit -n(软限制)、ulimit -Hn(硬限制) - 临时提高(仅本会话):
ulimit -n 65536;若要提硬限制,需 root 权限:sudo su -c "ulimit -Hn 65536; exec bash" - 注意:systemd 启动的服务完全不走这一层,改了也没用
2. 用户级限制(/etc/security/limits.conf,登录后生效)
适用于 SSH、su、图形终端等 PAM 登录场景,是普通用户服务(如 Java 应用、Node.js)最常用的持久化配置方式。
- 编辑
/etc/security/limits.conf或新建/etc/security/limits.d/10-fd.conf: appuser soft nofile 65536appuser hard nofile 65536-
* soft nofile 65536(所有用户) - 确认 PAM 已加载:
/etc/pam.d/common-session中必须含session required pam_limits.so - 必须全新登录(不是
source或su -)才能生效,验证命令:ulimit -n
3. systemd 服务级限制(unit 文件,服务重启生效)
所有由 systemctl start 启动的服务(nginx、redis、docker、自研后台)都走这一层,limits.conf 对它们完全无效。
- 查服务 unit 路径:
systemctl show myapp.service | grep FragmentPath - 新建覆盖配置:
sudo mkdir -p /etc/systemd/system/myapp.service.d,再创建limits.conf - 内容示例:
[Service] LimitNOFILE=65536 LimitNPROC=4096
- 重载并重启:
sudo systemctl daemon-reload && sudo systemctl restart myapp.service - 验证:
systemctl show myapp.service | grep LimitNOFILE或查进程:cat /proc/$(pgrep -f myapp)/limits | grep "Max open files"
4. 系统级内核限制(fs.file-max,全局总上限)
这是所有进程打开文件数的“天花板”,单位是系统级总数,不是单个进程。低于它,上面三层才可能生效。
- 查看当前值:
cat /proc/sys/fs/file-max - 临时修改:
sudo sysctl -w fs.file-max=2097152 - 永久生效:写入
/etc/sysctl.conf:fs.file-max = 2097152,然后运行sudo sysctl -p - 补充建议:同步设置
fs.nr_open = 2097152(单进程可设的最大 fd 上限,避免 ulimit -n 超过此值时报错)











