ulimit -n 修改未生效的核心原因是硬限制未提升且 systemd 服务不读取 /etc/security/limits.conf;需先调高硬限制并重新登录,systemd 服务须单独配置 limitnofile。

改了 ulimit -n 却没生效,不是命令写错了,而是你没碰对生效路径。 大多数人卡在“为什么加了配置还是 1024”,核心就两点:硬限制拦着软限制、systemd 服务压根不读 /etc/security/limits.conf。
ulimit -n 修改后立即失效的常见原因
执行 ulimit -Sn 65535 报错或无效,大概率是硬限制(hard limit)卡得太低。普通用户无法突破硬限制,而硬限制默认由 PAM 在登录时加载,不是靠当前 shell 命令能抬高的。
- 先查硬限制:
ulimit -Hn—— 如果输出是4096或更低,ulimit -Sn就不可能设到 65535 - 临时提硬限需 root:
sudo ulimit -Hn 65535(仅当前会话有效,且子进程继承软限,不自动继承新硬限) - 普通用户无法自行提升硬限,必须靠
/etc/security/limits.conf配置并重新登录 - 注意:只打开新终端窗口 ≠ 重新登录,必须 SSH 重连、或图形界面登出再进
/etc/security/limits.conf 配置后不生效的排查点
写了 * soft nofile 65535 和 * hard nofile 65535 却没用,八成是 PAM 模块没加载或加载顺序被覆盖。
- 确认
/etc/pam.d/common-session中有未注释行:session required pam_limits.so - CentOS/RHEL 7+ 等系统还要检查
/etc/pam.d/system-auth,同样需含该行 - 避免混用通配符和具体用户名 —— 例如
*和www-data同时存在时,PAM 按文件顺序取第一个匹配项,后者可能被前者盖掉 - 验证是否生效:登录后立刻跑
ulimit -n;再用ps -o pid,uid,comm -u $(whoami)确认进程 UID 确实是你本人(防误用 root 或其他用户身份启动)
systemd 服务的文件句柄限制必须单独设
/etc/security/limits.conf 对 systemd 管理的服务完全无效 —— 因为 systemd 进程本身不走 PAM 登录流程,它启动的子服务自然也收不到那些限制。
- 单个服务:编辑其 unit 文件,如
/etc/systemd/system/nginx.service,在[Service]段下加:LimitNOFILE=65535 - 全局生效:改
/etc/systemd/system.conf,在[Manager]下加:DefaultLimitNOFILE=65535 - 改完必须重载配置:
sudo systemctl daemon-reload,再重启服务(sudo systemctl restart nginx) - 验证方式:
systemctl show nginx | grep LimitNOFILE或查进程实际值:cat /proc/$(pgrep nginx)/limits | grep "Max open files"
系统级总句柄数也要同步调高
单个进程开到 65535 没用,如果内核总池子太小(fs.file-max),照样报 Too many open files。
- 查当前值:
cat /proc/sys/fs/file-max - 临时调高(重启失效):
sudo sysctl -w fs.file-max=1048576 - 永久生效:往
/etc/sysctl.conf追加一行:fs.file-max = 1048576,再运行sudo sysctl -p - 注意:这个值建议设为单进程最大值 × 预估并发进程数,别盲目堆到几百万,否则内存和调度开销会上升
最容易被忽略的是:systemd 服务和 PAM limits 是两套机制,不能互相替代;而硬限制就像一道门,软限制再怎么喊也没用,得先开门才能进门。











