ulimit -n 改了又变回 1024 是因该命令仅作用于当前 shell 会话,systemd 服务、sudo/su 启动进程不继承;需配置 /etc/security/limits.conf 并确保 pam 加载 pam_limits.so、用户重新登录,且 systemd 服务须在 unit 文件中设置 limitnofile 并重载。

ulimit -n 改了又变回 1024 怎么办
这不是配置没生效,而是 ulimit -n 本身只作用于当前 shell 会话及其子进程,退出终端或新开终端就重置。更关键的是:systemd 服务、sudo -u user cmd、su - user 等方式启动的进程,根本不会继承你交互式 shell 的限制。
常见错误现象:
- root 下执行
ulimit -n 65536,再su - appuser,ulimit -n还是 1024 -
/etc/profile里加了ulimit -n 65536,但systemctl start nginx启动后仍报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行
推荐写法(以 appuser 为例):
appuser soft nofile 65536 appuser hard nofile 65536 root soft nofile 65536 root hard nofile 65536
systemd 服务的 LimitNOFILE 必须单独设
从 systemd 219+ 开始,systemd 启动的服务默认忽略 limits.conf,因为它们运行在独立 cgroup session 中。即使用户登录时 ulimit -n 显示 65536,systemctl start myapp 启动的进程仍只有默认 1024。
Linux 性能分析与调优专家,覆盖 CPU、内存、磁盘 I/O、网络、内核参数、编译优化、容器/K8s。适用场景:系统卡顿/高负载、内存不足/OOM/Swap 高、CPU 异常/iowait 高。
解决方法:在 service 文件中显式设置
- 编辑
/etc/systemd/system/myservice.service,或用systemctl edit myservice.service - 在
[Service]段下添加:LimitNOFILE=65536 - 若需软硬分离(旧版本不支持),可加
LimitNOFILESoft=65536和LimitNOFILEHard=65536,但多数场景直接用LimitNOFILE即可 - 别忘了重载并重启:
systemctl daemon-reload && systemctl restart myservice
验证是否生效:systemctl show myservice --property LimitNOFILE
怎么确认某进程实际用了多少文件描述符
别只信 ulimit -n 输出值,得看真实进程。软限制决定实际能打开多少,硬限制只是上限;而服务是否真拿到了这个限制,得查运行时状态。
- 查系统总上限:
cat /proc/sys/fs/file-max - 查某用户登录后的限制:
su - appuser -c 'ulimit -n'(必须用-c触发新 shell) - 查某进程已打开的 fd 数:
ls /proc/<pid>/fd | wc -l</pid>(<pid></pid>替换为实际 PID) - 查进程实际生效的限制:
cat /proc/<pid>/limits | grep "Max open files"</pid>
最容易被忽略的一点:容器内进程受宿主机和容器 runtime 双重限制。即使宿主机改了 limits.conf 或 LimitNOFILE,docker run 时也得加 --ulimit nofile=65536:65536,否则容器内进程仍卡在默认值。










