最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
Linux如何排查系统句柄数超限问题:修改file-max与ulimit
时间:2026-06-04 08:04:07 编辑:袖梨 来源:一聚教程网
应先分层验证系统级(file-nr第二列)与进程级(/proc/pid/limits)实际使用量,再定位泄漏源而非盲目调参;systemd服务需配LimitNOFILE,容器须在运行时指定ulimit,且file-max须≤nr_open以防静默失败。
句柄超限不是“调大就完事”,而是先确认是不是真满了、谁在吃、为什么不吃完不吐——否则改完 file-max 或 ulimit 只是把崩溃时间往后拖一天。
怎么看系统到底满没满
别只看报错,得拆成两层验证:系统级总量 vs 进程级限额。
-
cat /proc/sys/fs/file-max是内核允许的全局上限,比如 1048576;但真正压垮系统的,往往是第二列:cat /proc/sys/fs/file-nr输出三列,第二列才是“已分配未释放”的 fd 数,它接近第一列才危险 -
ulimit -n显示当前 shell 的软限制,默认常为 1024;但进程可能继承了更小的值,得查真实运行时:用cat /proc/$(pidof nginx)/limits | grep "Max open files",看 Soft Limit 到底是多少 - 如果
lsof -p <pid> | wc -l</pid>结果远超 Soft Limit,那进程早该报Too many open files——但没报?说明它根本没走标准 open() 路径(比如用了memfd_create()),或者被 systemd 的LimitNOFILE覆盖了
为什么改了 /etc/security/limits.conf 却不生效
因为大多数现代 Linux 发行版(尤其是用 systemd 的)根本不会读这个文件来启动服务。
- 对交互式登录用户:改
/etc/security/limits.conf后必须新开一个 login shell(不是su或ssh子会话),且要确认/etc/pam.d/common-session包含session required pam_limits.so - 对 systemd 服务(如 nginx、redis):
limits.conf完全无效,必须在 service 文件里加LimitNOFILE=65536,例如写到/etc/systemd/system/nginx.service.d/override.conf中再systemctl daemon-reload - 容器环境(Docker/K8s):宿主机改了没用,得在
docker run --ulimit nofile=65536:65536或 Pod 的securityContext.fdsLimit里设
file-max 和 nr_open 不能乱调
file-max 不是越大越好,它直接消耗内核内存(每个 fd 约占 1KB),而 nr_open 是单个进程能申请 fd 的硬上限,必须 ≥ file-max,否则连 ulimit -n 都设不到想要的值。
- 临时调大:
sysctl -w fs.file-max=2097152,但重启失效 - 永久生效:写入
/etc/sysctl.conf,同时检查fs.nr_open是否够用,可用cat /proc/sys/fs/nr_open查;若不够,需在内核启动参数加nr_open=2097152(修改/etc/default/grub后update-grub && reboot) - 注意:某些云厂商镜像(如阿里云 CentOS)默认
nr_open只有 1048576,你设file-max=2097152会静默失败,sysctl -p也不报错
真正该花时间的地方:定位泄漏而非调参
调参顶多买 2 小时窗口,泄漏不修,下次还爆。重点看三类 fd:
- 大量
socket处于CLOSE_WAIT:说明本端没 close(),常见于 Java 的Socket忘关、Node.js 的net.Socket没destroy() - 一堆
anon_inode或eventpoll:epoll 实例没close(),多见于 C/C++ 自研网络库或 Go 的net.Conn泄漏 - 重复路径的日志文件(如
/var/log/app.log.1,.2,.3):logrotate 没配copytruncate或程序没响应SIGHUP,导致旧 fd 一直挂着 - 用
lsof -p <pid> | awk '$5 ~ /IPv|sock/ {print $9}' | sort | uniq -c | sort -nr</pid>快速筛出高频 socket 目标,比干看数字有用得多
最常被忽略的一点:很多“泄漏”其实来自子进程继承了父进程的 fd,但没设 FD_CLOEXEC 标志——尤其 fork+exec 场景下,父进程开了 5000 个连接,子进程一启就平白多 5000 个 fd,却没人意识到。
相关文章
- 侠盗飞车如何开飞机 侠盗飞车:自由城故事中的空中冒险 06-05
- nba2k13mc存档:NBA 2K13 MC存档全面解析:打造你的篮球传奇 06-05
- 超凡先锋牧狼人任务怎么完成 超凡先锋牧狼人任务操作流程分享 06-05
- 概率电路:快速且富有表现力的多字节预测 06-05
- 超凡先锋瞄具属性有哪些 超凡先锋瞄具属性详细介绍 06-05
- 超凡先锋黑屏闪退怎么办 超凡先锋黑屏闪退方法介绍 06-05