ulimit -n 修改不生效是因为它仅作用于当前shell及子进程,且不能超过系统硬限制;需通过/etc/security/limits.conf(配合pam)、systemd的limitnofile或root权限临时提升硬限制来持久生效。

ulimit -n 显示的数值为什么改了不生效
因为 ulimit -n 只影响当前 shell 及其子进程,且不能超过系统级硬限制(hard limit)。你用 ulimit -n 65536 设置后立刻生效,但新开终端、重启服务或 systemd 启动的进程完全不受影响。
常见错误现象:ulimit -n 输出是 1024,但程序一启动就报 Too many open files;或者临时改了,systemctl restart nginx 后又回到旧值。
- 先用
ulimit -Hn看硬限制,如果它只有 4096,那ulimit -n 65536会直接失败 - 临时提硬限制需 root 权限:
sudo ulimit -Hn 65536(仅当前 shell 有效) - 非 root 用户无法提升硬限制,只能降低或维持原值
/etc/security/limits.conf 配置后仍不生效
这是最常踩的坑:配置写了,但没被读取。根本原因是 PAM 模块未启用 limits,或者服务绕过了 login shell(比如直接用 systemd 启动)。
使用场景:想让 nginx、redis 或自研后台服务启动时自动获得高 fd 限制。
- 确认
/etc/pam.d/common-session(Debian/Ubuntu)或/etc/pam.d/login(RHEL/CentOS)里有这行:session required pam_limits.so -
limits.conf中用户名或组名必须精确匹配,*表示普通用户,root需单独配,@wheel这类组名要确保存在 - 格式必须严格:
username soft nofile 65536和username hard nofile 65536两行都得写,缺一不可 - 改完要重新登录(不是新开 terminal 标签页),或用
su - username切换才能加载新 limits
systemd 服务无视 limits.conf 怎么办
systemd 有自己的资源控制机制,完全不读 limits.conf。如果你用 systemctl start redis,那它的 nofile 值只由 service 文件里的 LimitNOFILE= 决定,或 fallback 到 systemd 默认值(通常是 1024)。
Zynq‑7000 / Zynq UltraScale+ 硬件调试技能。适用于 Xilinx Zynq(Cortex‑A9/A53 + FPGA)Linux 环境,调试 I2C、I2S、UART、GPIO 等外设。包括设备树配置、内核驱动、用户空间调试工具、交叉编译和常见问题排查,支持 PetaLinux 开发。
参数差异:LimitNOFILE= 可设单个值(如 65536),也可设软硬双值(65536:65536),后者等价于 soft/hard。
- 编辑服务文件:
sudo systemctl edit redis-server,然后加:[Service] LimitNOFILE=65536
- 不要直接改
/usr/lib/systemd/system/xxx.service,用systemctl edit才能避免包升级覆盖 - 改完必须
sudo systemctl daemon-reload,再sudo systemctl restart redis-server - 验证是否生效:
systemctl show redis-server | grep LimitNOFILE或查进程:cat /proc/$(pidof redis-server)/limits | grep "Max open files"
检查最终生效值该看哪里
别只信 ulimit -n,它只反映当前 shell 的软限制。真正决定程序行为的是进程打开时实际继承到的值,而这个值可能来自 shell、login、systemd、甚至程序自己调用 setrlimit()。
性能影响:设太高(比如 100 万)一般无害,但内核会为每个 fd 分配少量内存;设太低(
- 查某进程真实限制:
cat /proc/<pid>/limits | grep "Max open files"</pid>,注意看 “Soft Limit” 和 “Hard Limit” 两列 - 查当前 shell 的完整限制:
ulimit -a,重点比对open files行 - 如果程序是 fork 出来的子进程,它继承的是父进程当时的
rlimit,不是父进程当前ulimit值 - 容器环境(Docker/Podman)还要额外检查
--ulimit nofile=65536:65536或 pod spec 中的securityContext
真正麻烦的是多层叠加:PAM limits + systemd LimitNOFILE + 容器 ulimit + 程序 runtime 调整 —— 最终值取其中最小的那个。调试时得一层层剥开看,不能只改一处就以为万事大吉。










