从一个未释放文件描述符导致Linux系统假死的恶性生产事故中吸取教训

秋萱君_1030

秋萱君_1030

2026-06-03

559人浏览

原创

fd耗尽是linux“假死”的隐蔽元凶,因内核在tcp三次握手阶段拒连且不记日志,导致sshd失联、新连接失败但系统仍可ping通;需通过/proc/sys/fs/file-nr等命令快速定位并分层防控。

从一个未释放文件描述符导致linux系统假死的恶性生产事故中吸取教训

文件描述符(FD)耗尽是Linux系统“假死”的隐蔽元凶之一——它不触发OOM Killer,不写错误日志,甚至让sshd进程完全失联,而系统本身仍能ping通。问题根源在于:内核在TCP三次握手阶段就拒绝新连接,连SYN包都不进应用层,所以你查不到进程异常、看不到日志报错、用ps或top也一切正常。

为什么FD耗尽会导致“假死”而非崩溃

Linux把每个socket、pipe、open()的文件都算作一个FD。当全局FD池(/proc/sys/fs/file-nr中第一个数)逼近file-max上限时:

  • 新accept()调用直接返回EMFILE错误,Web服务无法建立新连接
  • sshd子进程fork失败,导致新SSH会话无法创建(但已有连接可能维持)
  • 后台任务如日志轮转、健康检查脚本因open()失败而静默退出,加剧不可见性
  • 内核不再记录此类拒绝,dmesg和/var/log/messages通常空空如也

如何快速确认是FD耗尽引发的假死

即使SSH连不上,只要还能console直连或通过带外管理(如iDRAC/IPMI)访问,立即执行:

CMIC Skill Scanner (Linux ARM64)
CMIC Skill Scanner (Linux ARM64)

使用 auto、native 或 external 引擎审计待安装的 skill 包或归档,并可选启用 LLM 语义分析。

下载
  • cat /proc/sys/fs/file-nr —— 若第一列接近第三列(如 9223372036854775800 0 9223372036854775807),基本锁定
  • lsof -n | awk '{print $2}' | sort | uniq -c | sort -nr | head -5 —— 查出FD大户PID
  • ls -l /proc/[PID]/fd | wc -l —— 精确查看某进程打开了多少FD
  • cat /proc/[PID]/limits | grep "Max open files" —— 看该进程是否被ulimit限制住,还是它自己泄漏了

两类典型泄漏场景与修复要点

场景一:长连接服务未关闭socket
如Node.js/Python服务中HTTP客户端复用连接池,但未设置超时或未正确close响应体,导致TIME_WAIT socket堆积且FD未释放。

  • 临时缓解:kill掉泄漏进程(别只kill -HUP,要确保彻底退出)
  • 代码修复:显式调用response.close()或使用with上下文;设置keep_alive_timeout和max_connections

场景二:子进程继承父进程FD
主进程打开大量文件或监听端口后fork子进程,子进程未调用close()就exec新程序,导致FD被意外持有。

  • 预防:fork前用fcntl(fd, F_SETFD, FD_CLOEXEC)设关闭标志
  • 排查:对比lsof -p [parent_pid]和lsof -p [child_pid],看是否有不该出现的FD重复

永久防御机制不能只靠调大上限

把fs.file-max从默认的几十万调到百万,只是延缓爆炸时间。真正有效的防线是分层控制:

  • 服务级:systemd服务配置LimitNOFILE=65536,避免单个服务吃光全局FD
  • 用户级:在/etc/security/limits.conf中为运行用户设软硬限制,如* soft nofile 65536
  • 监控项:将cat /proc/sys/fs/file-nr | awk '{print $1/$3*100}'纳入Prometheus+Alertmanager告警(建议阈值85%)
  • 启动检查:关键服务启动脚本开头加[[ $(ulimit -n) -lt 65536 ]] && echo "FD limit too low" >&2 && exit 1

相关专题

更多
磁盘配额是什么
磁盘配额是什么

磁盘配额是计算机中指定磁盘的储存限制,就是管理员可以为用户所能使用的磁盘空间进行配额限制,每一用户只能使用最大配额范围内的磁盘空间。php中文网为大家提供各种磁盘配额相关的内容,教程,供大家免费下载安装。

2023.06.21

3750

4

如何安装LINUX
如何安装LINUX

本站专题提供如何安装LINUX的相关教程文章,还有相关的下载、课程,大家可以免费体验。

2023.06.29

3233

10

linux find
linux find

find是linux命令,它将档案系统内符合 expression 的档案列出来。可以指要档案的名称、类别、时间、大小、权限等不同资讯的组合,只有完全相符的才会被列出来。find根据下列规则判断 path 和 expression,在命令列上第一个 - ( ) , ! 之前的部分为 path,之后的是 expression。还有指DOS 命令 find,Excel 函数 find等。本站专题提供linux find相关教程文章,还有相关

2023.06.30

2333

5

linux修改文件名
linux修改文件名

本专题为大家提供linux修改文件名相关的文章,这些文章可以帮助用户快速轻松地完成文件名的修改工作,大家可以免费体验。

2023.07.05

5610

7

linux系统安装教程
linux系统安装教程

linux系统是一种可以免费使用,自由传播,多用户、多任务、多线程、多CPU的操作系统。本专题提供linux系统安装教程相关的文章,大家可以免费体验。

2023.07.06

5262

7

linux查看文件夹大小
linux查看文件夹大小

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。linux怎么查看文件夹大小呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.20

3133

8

linux查看ip命令
linux查看ip命令

本专题为大家提供linux查看ip命令相关文章内容,感兴趣的朋友可以免费下载体验试试。

2023.07.20

2625

4

linux查看cpu使用率
linux查看cpu使用率

在linux的系统维护中,可能需要经常查看cpu使用率,分析系统整体的运行情况。本专题为大家带来了linux查看cpu使用率的相关文章,感兴趣的朋友千万不要错过了。

2023.07.25

2839

6

linux查找文件命令
linux查找文件命令

Linux是一种自由和开放源码的类Unix操作系统,存在着许多不同的Linux版本,但它们都使用了Linux内核。Linux可安装在各种计算机硬件设备中,比如手机、平板电脑、路由器、视频游戏控制台、台式计算机、大型机和超级计算机。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

2023.07.31

277

3

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习