直接读/proc/[pid]/limits是最准确方式,如cat /proc/1234/limits | grep "max open files",第三列为软限制、第四列为硬限制,需按字段名匹配而非行号,且调用方须有读取权限。

怎么看某个进程当前的文件句柄限制
直接读 /proc/<pid>/limits</pid> 是最准的方式,它反映该进程启动时继承或被设置的软硬限制。比如查 PID 1234:
cat /proc/1234/limits | grep "Max open files"
输出类似:
Max open files 1024 4096 files
第一列是软限制(soft limit),第二列是硬限制(hard limit)。注意:这个值不等于当前已打开的句柄数,只是上限。
- 软限制可由进程自己调用
setrlimit(RLIMIT_NOFILE, ...)降低,或由 root 提升(但不能超过硬限制) - 硬限制只能由 root 修改,且修改后子进程会继承该值
- 如果进程是 systemd 启动的,
/proc/<pid>/limits</pid>的值通常来自 systemd 的LimitNOFILE=配置,而非 shell ulimit
为什么改了 /proc/pid/limits 却没生效
/proc/<pid>/limits</pid> 是只读接口,写入会报 Operation not permitted —— 它不是配置文件,只是内核暴露的状态快照。
- 试图用
echo "..." > /proc/1234/limits一定会失败 - 想临时调高某进程的限制,必须在它启动前设好环境(如用
ulimit -n 65536再执行命令) - 对已运行进程,唯一办法是让它自己调用
setrlimit()(需代码支持),或者重启并带新限制启动
systemd 服务如何正确设置文件句柄数
这是生产环境最常出错的地方。直接改 /etc/security/limits.conf 对 systemd 管理的服务基本无效,因为 systemd 绕过了 PAM limits。
- 应在服务单元文件中加
LimitNOFILE=65536(同时设软硬限,默认软=硬) - 若要区分软硬限,写成
LimitNOFILE=4096:65536(软:硬) - 改完记得重载:
systemctl daemon-reload && systemctl restart your-service - 验证是否生效:重启后查
/proc/<pid>/limits</pid>,别只看ulimit -n的 shell 值
ulimit 和 /etc/security/limits.conf 的适用场景
这两者只影响通过 login shell 启动的**交互式进程或子 shell 进程**,比如你 ssh 登录后手动跑的 python server.py。
-
/etc/security/limits.conf中的* soft nofile 65536对 root 用户无效(除非显式写root) - 普通用户修改需退出当前 session 重新登录才生效;root 可用
su - $USER测试 - 脚本里用
ulimit -n 65536只对后续子进程有效,不影响父 shell 或已存在的进程 - 容器内(如 Docker)默认受宿主机 cgroup 限制,
ulimit可能被覆盖,得配--ulimit nofile=65536:65536
改 /proc/<pid>/limits</pid> 本身不可行,关键在“进程启动前”把限制钉死——systemd 单元、容器参数、shell wrapper 或启动脚本里的 ulimit,选哪个取决于进程怎么来的。漏掉这一层,后面所有排查都是在看假数据。











