65

我最近有一个 Linux 进程“泄露”了文件描述符:它打开了它们,但没有正确关闭其中的一些。

如果我对此进行了监控,我可以提前知道该过程已达到极限。

是否有一种不错的 Bash 或 Python 方法来检查 Ubuntu Linux 系统中给定进程的 FD 使用率?

编辑:

我现在知道如何检查有多少打开的文件描述符;我只需要知道一个进程允许多少个文件描述符。某些系统(如 Amazon EC2)没有该/proc/pid/limits文件。

4

7 回答 7

128

计算 中的条目/proc/<pid>/fd/。可在 中找到适用于该过程的硬限制和软限制/proc/<pid>/limits

于 2009-08-31T12:34:13.950 回答
34

Linux 内核提供的用于获取资源限制的唯一接口getrlimit()/proc/pid/limitsgetrlimit()只能获取调用进程的资源限制。 /proc/pid/limits允许您获取具有相同用户 ID 的任何进程的资源限制,并且可用于 RHEL 5.2、RHEL 4.7、Ubuntu 9.04 以及任何具有 2.6.24 或更高版本内核的发行版。

如果您需要支持较旧的 Linux 系统,则必须让进程本身调用getrlimit(). 当然,最简单的方法是修改程序或它使用的库。如果您正在运行该程序,那么您可以使用LD_PRELOAD将您自己的代码加载到程序中。如果这些都不可能,那么您可以使用 gdb 附加到进程并让它在进程中执行调用。您也可以自己执行相同的操作ptrace()来附加到进程、将调用插入其内存等,但是这样做非常复杂,不推荐。

使用适当的权限,其他方法将涉及查看内核内存、加载内核模块或以其他方式修改内核,但我假设这些都是不可能的。

于 2009-09-06T00:45:50.943 回答
2

您可以尝试编写定期调用lsof -p {PID}给定 pid 的脚本。

于 2009-08-31T09:41:28.557 回答
2

您要求使用 bash/python 方法。ulimit 将是最好的 bash 方法(缺少/proc/$pid/fd手动修改等)。对于 python,您可以使用资源模块。

import resource

print(resource.getrlimit(resource.RLIMIT_NOFILE))
$ python test.py

(1024, 65536)

resource.getrlimit对应getrlimit于 C 程序中的调用。结果代表所请求资源的当前值和最大值。在上面的示例中,当前(软)限制为 1024。这些值是当今 Linux 系统上的典型默认值。

于 2009-09-05T13:02:13.553 回答
2

查看使用进程的前 20 个文件句柄:

for x in `ps -eF| awk '{ print $2 }'`;do echo `ls /proc/$x/fd 2> /dev/null | wc -l` $x `cat /proc/$x/cmdline 2> /dev/null`;done | sort -n -r | head -n 20

输出格式为 file handle count, pid, cmndline for process

示例输出

701 1216 /sbin/rsyslogd-n-c5
169 11835 postgres: spaceuser spaceschema [local] idle
164 13621 postgres: spaceuser spaceschema [local] idle
161 13622 postgres: spaceuser spaceschema [local] idle
161 13618 postgres: spaceuser spaceschema [local] idle
于 2013-06-21T14:56:29.260 回答
0

在 CentOS 6 及以下(任何使用 GCC 3 的系统)中,您可能会发现调整内核限制并不能解决问题。这是因为FD_SETSIZE值是在 GCC 使用的编译时设置的。为此,您需要增加该值,然后重新编译该过程。

此外,如果您使用该库,您可能会发现由于libpthread中的已知问题而泄漏了文件描述符。这个调用在 GCC 4 / CentOS7 / RHEL 7 中被集成到 GCC 中,这似乎已经解决了线程问题。

于 2017-03-29T20:05:40.370 回答
0

使用优秀的 psutil 包的 Python 包装器:

import psutil

for p in psutil.process_iter(attrs=['pid', 'name', 'username', 'num_fds']):
    try:
        soft, hard = p.rlimit(psutil.RLIMIT_NOFILE)
        cur = p.info['num_fds']
        usage = int(cur / soft * 100)
        print('{:>2d}% {}/{}/{}'.format(
            usage,
            p.info['pid'],
            p.info['username'],
            p.info['name'],
            ))
    except psutil.NoSuchProcess:
        pass
于 2018-03-18T19:11:59.280 回答