ulimit 限制需按进程启动路径正确配置:pam 登录会话生效于 limits.conf,systemd 服务须在 unit 文件中设 limitnofile,且需调优 fs.file-max 和 fs.nr_open 内核参数。

进程资源限制(ulimit)不是单纯靠改一个文件就能生效的机制,它本质是 Linux 内核对单个进程可使用资源的硬性约束,而配置文件只是在特定登录路径中“触发”这些约束的手段。要真正控制并发上限(比如高并发服务能维持多少 TCP 连接),关键在于让目标进程在启动时实际获得所需的 nofile 限制,而不是只改了配置却没走对加载路径。
核心原理:限制只对“PAM 登录会话”生效
/etc/security/limits.conf 不是系统全局开关,它是 PAM 模块 pam_limits.so 的配置文件,只在用户通过 login、sshd、gdm 等调用了该模块的登录流程中起作用。这意味着:
- 直接用
su - user或sudo -i切换用户,通常能加载 limits.conf; - 但 systemd 服务、crond 启动的任务、docker 容器内进程、或 root 直接 fork 的后台程序,默认不经过 PAM 登录流程,完全忽略 limits.conf;
- 即使改了 limits.conf,如果 /etc/pam.d/sshd 或 /etc/pam.d/system-auth 中没有
session required pam_limits.so,SSH 登录也不会应用限制。
正确配置用户级并发上限(适用于交互式或 shell 启动的服务)
若服务由普通用户手动启动(如测试环境中的 Java Web 应用),按以下步骤设置打开文件数上限:
- 编辑
/etc/security/limits.conf,添加例如:myappuser soft nofile 65535myappuser hard nofile 65535 - 确认 PAM 配置已启用:检查
/etc/pam.d/sshd或/etc/pam.d/login是否包含session required pam_limits.so(CentOS 7+/RHEL 8+ 通常默认存在); - 用户必须全新登录(退出再 SSH 进来,不能仅用
source ~/.bashrc),之后运行ulimit -n应显示 65535; - 启动服务前,确保在该 shell 中执行,子进程才会继承该限制。
真正控制服务进程并发上限(推荐用于生产环境)
对于 systemd 管理的长期运行服务(如 nginx、redis、自研 daemon),不能依赖用户登录会话。应直接在 service unit 文件中声明限制:
- 编辑服务单元文件,如
/etc/systemd/system/myapp.service; - 在
[Service]小节下添加:LimitNOFILE=65535LimitNPROC=8192
(也可设为infinity,但需配合内核参数) - 重载配置并重启服务:
systemctl daemon-reload && systemctl restart myapp; - 验证:用
cat /proc/$(pgrep -f "myapp")/limits | grep "Max open files"查看实际生效值。
配套内核级调优(避免“有上限却用不了”)
用户级 ulimit 受限于系统总容量。若设了 65535 却仍报 “Too many open files”,说明内核全局限制太低:
- 编辑
/etc/sysctl.conf,追加:fs.file-max = 2097152fs.nr_open = 2097152 - 执行
sysctl -p生效; - 注意:
fs.nr_open是单进程nofile硬限制的绝对上限,必须 ≥ 所有服务设定的LimitNOFILE值; - TCP 连接还涉及端口范围,高并发时建议补充:
net.ipv4.ip_local_port_range = 1024 65535











