psutil.Process 和 lsof 命令不一致

问题描述

我编写了一个简单的 Python 脚本,用于监控 Red Hat 系统上的文件描述符数量

Init? _initData; City get selectedCity { return _initData!.cities .firstWhere((element) => element.id == _initData!.selectedCityId); } Init get initData => _initData!;// home_viewmodel.dart 25 命令相比,我得到两个不同的结果。

分解为核心,脚本执行以下操作:

lsof

当前 import psutil p = psutil.Process(PID) print(p.num_fds()) 报告 60 个打开的文件描述符。 而对于相同的 PID,num_fds() 的结果产生 167

这种差异从何而来?

我的理解是,lsof -p PID | wc -lnum_fds() 都报告相同的文件描述符,包括打开的文件句柄、套接字、管道等。

小背景:某些进程似乎打开套接字和/或文件句柄而不会再次关闭它们。因此,经过较长时间后,进程达到文件描述符的限制并崩溃。此工具旨在监控此过程,以防文件描述符的数量不断增加

解决方法

如果您查看 psutil 的源代码,您会发现 num_fds() 只是在计算 /proc/<pid>/fd 中的“文件”:

# _pslinux.py

@wrap_exceptions
def num_fds(self):
    return len(os.listdir("%s/%s/fd" % (self._procfs_path,self.pid)))


而且 lsof 可能会做更多的工作(例如它分析 process_proc_map() 中的内存映射):https://github.com/lsof-org/lsof/blob/56d79ed56d14825f234783a867d6bd5676729b32/dialects/linux/dproc.c

,

查看GitHub中的psutil源码,该方法的实现是:

def num_fds(self):
    return len(os.listdir("%s/%s/fd" % (self._procfs_path,self.pid)))

所以它只是计算 /proc/pid 或等效位置中列出的文件描述符的数量。

查看我当前在 Red Hat 服务器上的进程,pid 目录包含 5 个文件描述符;但 lsof 报告 19 个打开的文件。查看完整的 lsof 输出,不同之处在于它列出了与数字文件描述符无关的内容。 lsof 手册页描述:

   FD         is the File Descriptor number of the file or:

                   cwd  current working directory;
                   Lnn  library references (AIX);
                   err  FD information error (see NAME column);
                   jld  jail directory (FreeBSD);
                   ltx  shared library text (code and data);
                   Mxx  hex memory-mapped type number xx.
                   m86  DOS Merge mapped file;
                   mem  memory-mapped file;
                   mmap memory-mapped device;
                   pd   parent directory;
                   rtd  root directory;
                   tr   kernel trace file (OpenBSD);
                   txt  program text (code and data);
                   v86  VP/ix mapped file;

因此,这种差异是因为 lsof 包括各种实际上并未映射到文件描述符的“打开文件”。