最准的数值在/proc/$pid/limits,它直接反映内核为该进程实际维护的软硬限制快照;查看当前shell真实限制应执行cat /proc/self/limits,而非仅依赖ulimit -a,因后者只显示会话软限制且可能被继承打折。

最准的数值不在 ulimit,而在 /proc/$pid/limits —— 它直接反映内核为该进程实际维护的软硬限制快照,不经过 shell 或 PAM 中转,也不受会话生命周期影响。
怎么看当前 shell 的真实限制?
别只信 ulimit -a,它只显示当前 shell 会话的软限制,且可能被子进程继承时“打折”。真正属于这个 shell 进程本身的完整限制,得看:
-
cat /proc/self/limits:显示当前 shell 进程的全部软硬限制,字段清晰(Soft Limit/Hard Limit/Units) -
ulimit -Sn和ulimit -Hn要配对看:比如ulimit -Sn输出1024,ulimit -Hn输出65536,说明你最多能临时提软限制到 65536,但不能超过硬限 - 注意单位陷阱:
-n是个数,-s(栈大小)和-v(虚拟内存)单位是 KB,-c(core 文件)单位是 512 字节块 —— 直接看/proc/self/limits的Units列最省心
怎么看某个后台服务进程的限制?
比如 nginx、redis 或你自己写的 daemon,ulimit -n 的结果跟它完全无关。必须用它的 PID 查:
Linux系统管理专家,覆盖12大模块:用户权限、SSH、存储、网络、systemd、防火墙、日志监控、备份恢复、TLS证书、Ansible、容器、IaC。提供配置、验证、加固、监控、备份、自动化、故障排查、回滚闭环。关键词:useradd、sudo、sshd_config、chmod、SEL...
- 先找 PID:
pgrep -f "nginx"或systemctl show nginx.service | grep MainPID - 再查限制:
cat /proc/1234/limits | grep "open files",输出类似Max open files 1024 65536 files - 如果提示
Permission denied,说明你不是 root 或非同用户 —— 普通用户无法读其他用户的/proc/$pid/limits - systemd 服务还要多看一层:
systemctl show myapp.service | grep LimitNOFILE,因为 unit 文件里的LimitNOFILE=可能覆盖 PAM limits.conf
为什么改了 limits.conf 却没生效?
因为 /etc/security/limits.conf 只在登录会话建立时由 PAM 加载,对已运行进程、systemd 直接启动的服务、cron 启动的任务都无效:
- SSH 登录后改了
limits.conf,得新开一个会话才生效;旧 shell 和它的子进程仍用老值 - systemd 服务默认忽略
limits.conf,必须在 service unit 文件里显式写LimitNOFILE=65536,然后systemctl daemon-reload && systemctl restart myapp - docker 容器里改 host 的
limits.conf没用 —— 容器有自己的 init 进程和 cgroup 限制,得通过--ulimit nofile=65536:65536启动时传入 - 即使看到
/proc/$pid/limits里Max open files是unlimited,也不代表真没限 —— 可能被 cgroup v2 的memory.max或pids.max间接卡住,得查/sys/fs/cgroup/.../pids.current
能不能直接改 /proc/$pid/limits?
不能。/proc/$pid/limits 是只读虚拟文件,echo 写入会报 Invalid argument 或 Permission denied:
- 唯一合法动态修改运行中进程限制的方式是
prlimit,例如:prlimit -p 1234 --nofile=65536:65536 - 但
prlimit受权限严格约束:普通用户只能调低软限或提至当前硬限内;提硬限必须 root - systemd 服务若配置了
LimitNOFILE=,prlimit改完可能被 watchdog 立刻拉回 —— 这不是 bug,是 systemd 的主动防护 - 子进程不会自动继承父进程被
prlimit修改后的限制,除非重新 exec,否则 fork 出来的还是原值
真正容易被忽略的点是:同一个进程的限制可能来自多个源头叠加(PAM + systemd unit + cgroup + seccomp),而 /proc/$pid/limits 显示的是最终生效值 —— 它不告诉你“谁设的”,只告诉你“现在是多少”。排查时得一层层反向验证,而不是只盯着一个输出。










