You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux下Python3统计进程打开文件描述符的高效方法

Linux下Python3高效统计进程打开文件描述符(FD)的方法

问题背景

使用libzmq的Python服务器存在FD泄漏问题(源于libzmq内部竞态条件,短期无法修复),需要进程自行检测FD数量,当累积到约500个时自动重启,无需外部监控干预。

高效FD计数方案

1. 读取/proc/self/stat获取精确计数(最优)

Linux系统中,/proc/self/stat文件的第24个字段(索引从0开始为第23位)直接记录了当前进程打开的FD总数,无需遍历目录,速度极快。

import os

def get_open_fds():
    with open('/proc/self/stat', 'r') as stat_file:
        stat_data = stat_file.read().split()
    return int(stat_data[23])

2. 用fcntl快速估算FD数量(次优)

通过fcntl.F_DUPFD_CLOEXEC系统调用尝试复制一个高编号的FD,返回的第一个可用FD值减1即为当前已用的最大FD编号。该方法无文件IO,速度最快,但结果是估算值(可能存在FD空洞,比如关闭了中间的FD),适合仅需判断阈值的场景。

import fcntl
import os

def estimate_open_fds():
    try:
        # 从1024开始尝试复制FD,返回第一个可用的FD
        new_fd = fcntl.fcntl(0, fcntl.F_DUPFD_CLOEXEC, 1024)
        os.close(new_fd)
        return new_fd - 1
    except OSError as e:
        if e.errno == 24:  # FD耗尽(EMFILE)
            return os.getrlimit(os.RLIMIT_NOFILE)[0]
        raise

3. 优化版遍历/proc/self/fd(精确但稍慢)

若必须精确计数且不想依赖/proc/self/stat,用os.scandir替代os.listdir遍历目录,os.scandir比传统遍历更高效,因为它无需额外调用stat获取条目信息。

import os

def count_open_fds():
    count = 0
    with os.scandir('/proc/self/fd') as entries:
        for _ in entries:
            count += 1
    return count

自动重启实现示例

结合FD计数逻辑,实现进程自动重启:

import os
import sys
import time

def get_open_fds():
    with open('/proc/self/stat', 'r') as stat_file:
        return int(stat_file.read().split()[23])

def main():
    while True:
        # 这里替换为你的服务器业务逻辑
        print("Server running...")
        
        # 定期检查FD数量(示例为每60秒检查一次)
        fd_count = get_open_fds()
        if fd_count >= 500:
            print(f"FD count reached {fd_count}, initiating restart...")
            # 用execv重启进程,替换当前进程空间,避免僵尸进程
            os.execv(sys.executable, [sys.executable] + sys.argv)
        
        time.sleep(60)

if __name__ == "__main__":
    main()

注意事项

  • 若允许依赖第三方库,psutil.Process().num_fds()是跨平台的精确计数方法,但会增加依赖。
  • 重启前需确保服务器优雅关闭,比如处理完当前请求、关闭连接,避免数据丢失。
  • 阈值(500)需低于系统FD软限制,可通过os.getrlimit(os.RLIMIT_NOFILE)[0]查看当前软限制。

内容的提问来源于stack exchange,提问作者Goswin von Brederlow

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 11:12:52