当前位置: 首页
业界动态
四个实验彻底搞懂Linux句柄泄漏和Too many open files

四个实验彻底搞懂Linux句柄泄漏和Too many open files

热心网友 时间:2026-06-15
转载

这篇文章,我们将通过几个简单脚本,亲手模拟一场典型的“句柄泄漏事故”,让你直观理解其发生机制与复现方法。

在上一篇文章中,我们分析了一个常见的线上故障:

Too many open files → 服务拒绝连接

很多开发者会疑惑:这个问题究竟是如何触发的?能否在本地环境进行复现?

本文我们将直接使用几个简易脚本,亲手复现一场“句柄泄漏事故”。

什么是文件描述符(FD)

在 Linux 系统中,一切资源皆被视为文件:

  • 普通文件
  • 网络 Socket
  • Pipe(管道)
  • 设备节点

这些资源均通过文件描述符(FD)进行统一管理。

每个进程可使用的 FD 数量都有上限:

ulimit -n

常见配置值:

  • 1024(系统默认)
  • 65535(经过优化后的典型值)

一旦 FD 被耗尽,便会触发:

Too many open files

实验一:最简单的 FD 泄漏场景

演示脚本(未主动关闭文件):

# fd_leak_file.py
import time
fds = []
while True:
    f = open("/tmp/test_fd.txt", "w")
    fds.append(f)  # ❗没有关闭
    print("opened:", len(fds))
    time.sleep(0.01)

运行实验:

ulimit -n 10000
python3 fd_leak_file.py
opened: 9993
opened: 9994
opened: 9995
opened: 9996
opened: 9997
Traceback (most recent call last):
  File "file_os.py", line 7, in 
OSError: [Errno 24] Too many open files: '/tmp/test_fd.txt'
# 检查文件描述符
[root@localhost ~]# ll /proc/4013078/fd -ltr
...
l-wx------ 1 root root 64  3月 24 22:27 9993 -> /tmp/test_fd.txt
l-wx------ 1 root root 64  3月 24 22:27 9994 -> /tmp/test_fd.txt
l-wx------ 1 root root 64  3月 24 22:27 9995 -> /tmp/test_fd.txt
l-wx------ 1 root root 64  3月 24 22:27 9996 -> /tmp/test_fd.txt

监控截图:

\

由此可见,只要持续打开文件而不关闭,FD 必然被耗尽。

实验二:模拟 Socket 连接泄漏

该场景更贴近实际服务:

# fd_leak_socket.py
import socket
import time
sockets = []
while True:
    s = socket.socket()
    s.connect(("127.0.0.1", 80))
    sockets.append(s)  # ❗不关闭
    print("socket:", len(sockets))
    time.sleep(0.01)

运行现象:

#脚本执行情况
socket: 9997
Traceback (most recent call last):
  File "fd_leak_socket.py", line 8, in 
  File "/usr/lib64/python3.7/socket.py", line 151, in __init__
OSError: [Errno 24] Too many open files
#检查句柄情况
[root@localhost ~]# ls -ltr /proc/1831260/fd
...
lrwx------ 1 root root 64  3月 25 16:29 104 -> 'socket:[1039854483]'
lrwx------ 1 root root 64  3月 25 16:29 103 -> 'socket:[1039854482]'
lrwx------ 1 root root 64  3月 25 16:29 102 -> 'socket:[1039854481]'
lrwx------ 1 root root 64  3月 25 16:29 101 -> 'socket:[1039854480]'
lrwx------ 1 root root 64  3月 25 16:29 100 -> 'socket:[1039854479]'
lrwx------ 1 root root 64  3月 25 16:29 10 -> 'socket:[1039845307]'
lrwx------ 1 root root 64  3月 25 16:29 1 -> /dev/pts/0
lrwx------ 1 root root 64  3月 25 16:29 0 -> /dev/pts/0
lrwx------ 1 root root 64  3月 25 16:30 9999 -> 'socket:[1040097407]'

lFD 数量持续增长,最终程序报错:

\

实验三(重点):触发 Pipe 泄漏

该场景正是许多线上故障的根源:

# fd_leak_pipe.py
import os
import time
pipes = []
while True:
    r, w = os.pipe()
    pipes.append((r, w))  # ❗不关闭
    print("pipe:", len(pipes))
    time.sleep(0.01)

验证步骤:
首先找到进程 PID

ps -ef | grep fd_leak_pipe

查看 FD 数量

[root@localhost ~]# ls -ltr /proc/1923060/fd
...
l-wx------ 1 root root 64  3月 25 16:36 9722 -> 'pipe:[1040687058]'
lr-x------ 1 root root 64  3月 25 16:36 9721 -> 'pipe:[1040687058]'
l-wx------ 1 root root 64  3月 25 16:36 9720 -> 'pipe:[1040687057]'
lr-x------ 1 root root 64  3月 25 16:36 9719 -> 'pipe:[1040687057]'
ls /proc/

/fd | wc -l

你会发现:

  • 已打开的文件描述符数量持续攀升
  • 短时间内即逼近系统上限

查看 FD 类型:

ls -l /proc/

/fd | grep pipe pipe:[xxxx] pipe:[xxxx] pipe:[xxxx]

该现象与众多线上生产故障完全吻合。

实验四:模拟真实服务场景(子进程泄漏)

此场景最贴近实际生产环境:

# fd_leak_subprocess.py
import subprocess
import time
procs = []
while True:
    p = subprocess.Popen(
        ["echo", "hello"],
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )
    procs.append(p)  # ❗不 wait、不关闭
    print("proc:", len(procs))
    time.sleep(0.01)

该实验会导致:

  • Pipe 数量急剧增加
  • 子进程不断堆积
  • 文件描述符迅速膨胀引发爆炸

与真实服务(如文档转换、后台任务执行)的故障模式高度一致。

为什么会发生泄漏?

根本原因只有一个:资源被申请后,始终未进行释放。

文件描述符(FD)泄漏可归纳为四大类:

  • 文件打开后未关闭
  • Socket 连接未释放
  • Pipe 管道未关闭
  • 子进程未等待(导致管道残留)

正确写法(避免泄漏):

import os
for i in range(10000):
    r, w = os.pipe()
    os.close(r)
    os.close(w)

或对子进程做:

p = subprocess.Popen(...)
p.wait()

如何快速判断是否存在泄漏?

方法1:观察 FD 数量是否持续增长

watch -n 1 "ls /proc/

/fd | wc -l"

方法2:按类型统计 FD 占比

ls -l /proc/

/fd | awk '{print $NF}' | cut -d: -f1 | sort | uniq -c

方法3:查看 Socket 状态

ss -antp

实验总结

上述几个实验印证了一个道理:文件描述符泄漏并非复杂难题,本质上是“忘记关闭资源”导致的。

但在生产环境中,由于:

  • 并发量高
  • 调用链复杂
  • 业务链路漫长

极易演变成灾难性后果:

FD耗尽 → 无法 accept → 服务雪崩

如果你在线上遇到:

  • 服务突然拒绝连接
  • 日志频繁出现Too many open files

第一件该做的事:

ls /proc/

/fd | wc -l

亲手动手模拟一遍,远比阅读十篇理论文章更有效。

来源:https://www.51cto.com/article/840899.html

游乐网为非赢利性网站,所展示的游戏/软件/文章内容均来自于互联网或第三方用户上传分享,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系youleyoucom@outlook.com。

同类文章
更多
南山紫琅湖携手共进,集成电路产业联动迎新机遇

南山紫琅湖携手共进,集成电路产业联动迎新机遇

2025年南通创新区紫琅硅谷推介会暨创新创业大赛深圳赛于11月14日举行。深圳集成电路产业2024年营收2839 6亿元,占广东总产值79%。南通创新区集聚科研院所和集成电路设计企业,两地形成芯片设计与制造封测互补的协同发展格局。

时间:2026-07-03 13:20
时空壶以技术沉淀践行巴别鱼理想引领跨语言交流

时空壶以技术沉淀践行巴别鱼理想引领跨语言交流

时空壶以巴别鱼为灵感,历经9年研发W4Pro开放式AI同传耳机,独创双工通信、矢量降噪与骨声纹识别技术,在85分贝环境下识别率98%以上;自研BabelOS2 0同传系统实现端云协同,同传准确率95%,适配96种口音,持有百余项全球专利。

时间:2026-07-03 13:19
海外实测时空壶新T1端侧AI技术翻译机破解无网沟通

海外实测时空壶新T1端侧AI技术翻译机破解无网沟通

时空壶新T1翻译机采用端侧AI离线语义理解,准确率90%,支持31组语言双向互译、0 5秒拍照翻译及0 2秒流式延迟,配合ENC降噪与内置eSIM两年流量,破解无网沟通难题。

时间:2026-07-03 13:19
荣耀CEO李健宣布明年推出机器人手机

荣耀CEO李健宣布明年推出机器人手机

荣耀CEO李健透露,明年将推出ROBOTPHONE,集成AI手机、具身智能与高清摄像。其采用可折叠升降模块化机械结构,后摄可展开为独立云台,兼具环境与情感交互能力,成为微型便携具身智能终端。该产品是荣耀阿尔法战略的关键节点。

时间:2026-07-03 13:19
京东与可以科技共绘情感交互机器人温暖未来

京东与可以科技共绘情感交互机器人温暖未来

京东与可以科技达成战略合作,共同进军智能情感交互机器人赛道。双方将融合京东AI大模型、智能生态与可以科技的情感交互技术,在Loona机器狗等产品上实现情感计算、长期记忆和个性化养成,让机器人从工具变为有温度的陪伴伙伴。

时间:2026-07-03 13:19
热门专题
更多
刀塔传奇破解版无限钻石下载大全 刀塔传奇破解版无限钻石下载大全
洛克王国正式正版手游下载安装大全 洛克王国正式正版手游下载安装大全
思美人手游下载专区 思美人手游下载专区
好玩的阿拉德之怒游戏下载合集 好玩的阿拉德之怒游戏下载合集
不思议迷宫手游下载合集 不思议迷宫手游下载合集
百宝袋汉化组游戏最新合集 百宝袋汉化组游戏最新合集
jsk游戏合集30款游戏大全 jsk游戏合集30款游戏大全
宾果消消消原版下载大全 宾果消消消原版下载大全
  • 日榜
  • 周榜
  • 月榜