ulimit -n 修改未生效是因为仅影响当前shell及其子进程,且软限制不能超过硬限制;硬限制需通过/etc/security/limits.conf配置并重新登录,或对systemd服务单独设置defaultlimitnofile/limitnofile。

ulimit -n 为什么改了没生效
常见现象是执行 ulimit -n 65535 后,新起的进程仍显示 1024。根本原因是:该命令只影响当前 shell 及其子进程,且软限制不能超过硬限制;而硬限制默认由 PAM 在登录时加载,未配置 limits.conf 时,硬限制通常卡在 4096 或更低。
实操建议:
- 先检查硬限制:
ulimit -Hn,若低于目标值(如65535),ulimit -Sn必然失败 - 临时提硬限需 root 权限:
sudo ulimit -Hn 65535(仅当前会话有效) - 普通用户无法提升硬限,必须靠
/etc/security/limits.conf配置并重新登录 - 注意:systemd 服务绕过 PAM,
limits.conf对它们无效,需单独设DefaultLimitNOFILE
/etc/security/limits.conf 配置后不生效的典型原因
写入 * soft nofile 65535 和 * hard nofile 65535 后仍不生效,大概率是 PAM 模块没启用或加载顺序错位。
实操建议:
- 确认
/etc/pam.d/common-session中存在且未被注释:session required pam_limits.so - 某些发行版(如 CentOS 7+)用的是
/etc/pam.d/system-auth,需同步检查该文件 - 避免在
limits.conf中混用通配符和具体用户名——例如*和www-data同时存在时,PAM 按匹配顺序取第一个,可能被覆盖 - 修改后必须**重新登录**(SSH 重连、图形界面登出再进),不是重启终端窗口
- 验证方式:登录后立即运行
ulimit -n,并用ps -o pid,uid,comm -u $(whoami)确认进程 UID 匹配预期用户
systemd 服务的 NOFILE 限制要单独处理
nginx、redis、node.js 等通过 systemctl start 启动的服务,完全无视 limits.conf。它们受 systemd 自身的资源限制控制,ulimit 命令查不到真实值。
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
实操建议:
- 全局生效:编辑
/etc/systemd/system.conf,取消注释并修改:DefaultLimitNOFILE=65535 - 单服务生效:在对应 unit 文件(如
/etc/systemd/system/nginx.service)的[Service]段下添加:LimitNOFILE=65535 - 修改后必须重载配置:
sudo systemctl daemon-reload,再sudo systemctl restart xxx - 验证方式:
systemctl show nginx | grep LimitNOFILE,或查看进程实际打开数:cat /proc/$(pidof nginx)/limits | grep "Max open files"
fs.file-max 和 net.core.somaxconn 的协同关系
fs.file-max 是内核级总句柄池上限,net.core.somaxconn 是 listen socket 的等待队列长度。两者不直接相等,但必须匹配业务规模:如果 fs.file-max 太小,即使单个进程开了 65535 句柄,系统也无法分配足够资源给所有连接;如果 net.core.somaxconn 过小,新连接会在内核队列排队超时丢弃,表现为“连接拒绝”而非“too many open files”。
实操建议:
-
fs.file-max推荐设为单机最大并发连接数 × 1.2~1.5 倍(如目标支撑 10w 连接,设1200000) -
net.core.somaxconn应 ≥ 单个服务监听 socket 的预期并发连接峰值(Web 服务一般设65535) - 修改后必须运行
sudo sysctl -p生效,且要确保/etc/sysctl.conf中有对应行,否则重启丢失 - 注意:某些云主机(如 AWS EC2)的
fs.file-max默认值极低(如 65536),不调优会成为硬瓶颈
真正容易被忽略的是:ulimit -n 查到的是进程软限,/proc/PID/limits 才反映该进程实际生效值,而 systemctl show 显示的是 systemd 给它设的硬限——三者可能完全不同。调优时必须分层验证,不能只看一个命令输出。










