ulimit -n 修改未生效主因是服务未读取pam限制:systemd服务需配limitnofile,limits.conf须明确soft/hard,用户需重新登录,且需同步调大fs.file-max和启用pam_limits.so。

ulimit -n 改了没生效?先看服务启动方式
很多用户改完 /etc/security/limits.conf 重启服务,ulimit -n 还是 1024——不是配置错了,是服务压根没读 PAM 限制。systemd 管理的服务(比如 nginx、mysql、redis)默认绕过 limits.conf,得单独配服务单元。
- 查服务是否用 systemd:运行
ps -p $(pgrep -f "nginx|mysql") -o comm=,输出带systemd就是 - 正确做法:用
systemctl edit nginx.service加LimitNOFILE=65536,再systemctl daemon-reload && systemctl restart nginx - 验证是否生效:查进程实际限制:
cat /proc/$(pgrep nginx)/limits | grep "Max open files",看Soft Limit和Hard Limit是否已更新
/etc/security/limits.conf 配置写法必须带 soft/hard
只写 * nofile 65536 是无效的。ulimit 区分软限(soft)和硬限(hard),普通用户只能调高软限到硬限范围内,root 才能调高硬限。漏写 soft 或 hard 关键字,整行被忽略。
- 正确写法示例:
* soft nofile 65536和* hard nofile 65536必须成对出现 - 针对特定用户更稳妥:
www-data soft nofile 65536+www-data hard nofile 65536(避免 * 影响所有用户) - 生效条件:用户需全新登录(SSH 重连),或用
su - www-data切换,直接su www-data不加载 PAM 限制
系统级 file-max 和用户级 nofile 是两回事
ulimit -n 是单个进程能打开的文件描述符上限;fs.file-max 是整个内核能分配的总文件描述符数。前者设再大,后者卡在 10 万,照样报 Too many open files。
- 查当前系统上限:
cat /proc/sys/fs/file-max - 临时提高:
echo 2097152 > /proc/sys/fs/file-max - 永久生效:往
/etc/sysctl.conf加fs.file-max = 2097152,再执行sysctl -p - 注意:file-max 建议设为 nofile × 用户并发进程数 × 1.2 左右,留点余量,别盲目堆到千万级
memlock unlimited 要配 PAM 才真生效
RDMA、DPDK、某些数据库(如 PostgreSQL 使用 huge pages)要求锁定内存,ulimit -l unlimited 却仍报 Cannot allocate memory——大概率是 PAM 没启用 pam_limits.so。
- 检查:
grep pam_limits /etc/pam.d/common-session,没结果就手动加一行:session required pam_limits.so - Ubuntu/Debian 系统特别容易漏这步,光改
limits.conf没用 - 验证:切到目标用户后运行
ulimit -l,返回unlimited才算到位;若仍是数字,说明 PAM 没加载成功
真正麻烦的从来不是改哪几行配置,而是改完之后不知道该去哪个进程里验证、也不知道该用哪个命令确认它到底有没有被内核采纳。尤其是 systemd 服务和 PAM 的配合点,错一个环节,前面全白调。










