必须从会话级、用户级、服务级三层同步设限,确保软硬限制逻辑正确、生效路径完整;需验证真实限制、正确配置pam模块、systemd服务单独加限,并补全内核级兜底参数。

要严控各服务账号的物理资源占用,不能只靠临时命令,得从会话级、用户级、服务级三层同步设限,并确保软硬限制逻辑正确、生效路径完整。核心是让每个服务账号(如 nginx、mysql、appuser)在启动时就带上明确的资源上限,避免默认值被滥用。
先查清当前真实限制,别被表面值误导
执行 ulimit -Sn 和 ulimit -Hn 分开看:软限制不能超过硬限制。如果 ulimit -Hn 是 1024,那 ulimit -Sn 再设 65535 也无效,系统会静默截断。普通用户只能调低或在硬限内调高软限;只有 root 能提硬限。验证时建议用目标账号登录后直接运行 ulimit -a,别在 root 下切过去就完事——su username 不触发 PAM,必须用 su - username(带短横)才加载 limits 配置。
对服务账号做用户级持久限制(/etc/security/limits.conf)
该配置只对通过 PAM 登录的会话生效,比如 SSH 登录、su -、图形终端等。编辑 /etc/security/limits.conf,为每个服务账号单独写两行:
nginx soft nofile 65535nginx hard nofile 65535mysql soft nproc 4096mysql hard nproc 4096appuser soft stack 8192appuser hard stack 8192
注意:soft 和 hard 必须成对出现,数值相等或软限 ≤ 硬限;不能写成 nginx - nofile 65535 这种简写,PAM 不识别;修改后需新登录才生效,已有终端不刷新。
确保 PAM 正确加载 limits 模块
没有这步,limits.conf 就是废纸。检查以下文件是否含 session required pam_limits.so:
-
/etc/pam.d/sshd(SSH 登录) -
/etc/pam.d/login(本地终端) -
/etc/pam.d/common-session(Debian/Ubuntu 系通用入口)
若使用 GNOME/KDE 图形界面,还需在 /etc/systemd/logind.conf 中取消注释并设:DefaultLimitNOFILE=65535
然后执行 systemctl restart systemd-logind。
给 systemd 托管的服务单独加限(绕过 limits.conf)
像 nginx、mysql 这类由 systemctl start 启动的服务,完全不走 PAM,limits.conf 对它们无效。必须在 service unit 文件里显式声明:
- 创建覆盖目录:
sudo mkdir -p /etc/systemd/system/nginx.service.d - 新建
/etc/systemd/system/nginx.service.d/override.conf,内容为:
[Service] LimitNOFILE=65535 LimitNPROC=4096 LimitRSS=2097152 LimitAS=4194304
其中 LimitRSS 限制常驻内存(KB),LimitAS 限制虚拟内存(KB)。改完执行:sudo systemctl daemon-reload && sudo systemctl restart nginx
补全系统级兜底参数(防越界)
用户级限制再严,也得有内核支撑。编辑 /etc/sysctl.conf 加入:
-
fs.file-max = 2097152(全系统最大文件描述符) -
vm.max_map_count = 262144(对 Elasticsearch 等内存映射密集型服务关键)
执行 sudo sysctl -p 生效。这些参数不限制单个用户,但设太低会导致即使用户限再宽也报“Too many open files”。











