ulimit -n 改后变回1024是因为该设置仅作用于当前shell会话,且systemd服务、pam管理的服务不继承交互式shell限制;需配置/etc/security/limits.conf并确保pam加载pam_limits.so、用户重新登录,或为systemd服务在service文件中设置limitnofile。

ulimit -n 为什么改了又变回1024
根本原因是:ulimit 命令本身只作用于当前 shell 会话及其子进程,退出终端就失效。更关键的是,很多服务(比如 nginx、java 应用、systemd 管理的服务)压根不读取你交互式 shell 的 ulimit 设置——它们由 PAM 或 systemd 独立加载资源限制。
常见错误现象:
- root 下执行
ulimit -n 65536,再su - appuser,ulimit -n还是 1024 - 在
/etc/profile里加ulimit -n 65536,但systemctl start myapp启动后仍报Too many open files - 改了
/etc/security/limits.conf,但没重启登录或没确认 PAM 是否启用pam_limits.so
/etc/security/limits.conf 配置必须满足的三个条件
这个文件不是“写了就生效”,它依赖 PAM 模块加载,且对不同启动方式效果不同。要让它起作用,得同时满足:
-
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/system-auth(RHEL/CentOS)中必须包含这一行:session required pam_limits.so - 用户必须重新登录(SSH 重连、console 重新登录),仅
su - user不一定触发完整 PAM session 初始化 - 配置格式不能错:
username soft nofile 65536和username hard nofile 65536必须分开写;若想全局生效,用*,但注意root默认被某些发行版策略绕过,建议显式写root行
示例(推荐写法):
Linux AI 服务器 — 将 Linux 服务器转换为本地 AI 推理集群。使用 systemd、NVIDIA CUDA 实现无头 Linux AI,零 GUI 开销。
root soft nofile 65536 root hard nofile 65536 * soft nofile 65536 * hard nofile 65536
systemd 服务绕过了 limits.conf?那得改 service 文件
从 systemd 219+ 开始,systemd 启动的服务默认忽略 limits.conf,因为它们运行在独立的 cgroup session 中。这时候即使 limits.conf 写对了,systemctl start nginx 依然只有 1024 个文件描述符。
解决方法:在对应 service 单元文件中显式设置:
- 编辑
/etc/systemd/system/myservice.service或使用systemctl edit myservice - 在
[Service]段下添加:LimitNOFILE=65536 - 如果还要设软硬一致,可加:
LimitNOFILESoft=65536和LimitNOFILEHard=65536(部分旧版本不支持 soft/hard 分设,直接用LimitNOFILE即可) - 别忘了重载并重启:
systemctl daemon-reload && systemctl restart myservice
fs.file-max 和 ulimit -n 是两回事,别混
fs.file-max 是内核级总上限,即整个系统能分配的文件描述符总数;而 ulimit -n 是单个进程(或用户 session)的上限。前者不够会导致所有用户都卡住,后者不够只影响单个应用。
- 查系统总上限:
cat /proc/sys/fs/file-max - 临时调高:
sysctl -w fs.file-max=1048576 - 永久生效:往
/etc/sysctl.conf加一行fs.file-max = 1048576,再运行sysctl -p - 注意:如果
fs.file-max小于某个用户的ulimit -n,该用户实际能用的仍是fs.file-max的值(会被截断)
真正容易被忽略的是:改完 limits.conf 或 sysctl.conf 后,不验证是否落地。务必用目标用户身份登录后执行 ulimit -n,并用 cat /proc/$(pgrep -f 'your_app')/limits | grep "Max open files" 查看进程实际看到的值。










