检查Linux中给定进程的开放FD限制

时间:2009-08-31 09:39:02

标签: linux scripting operating-system limit file-descriptor

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

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

在Ubuntu Linux系统中,是否有一个很好的Bash \ Python方法来检查给定进程的FD使用率?

修改

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

谢谢,

乌迪

7 个答案:

答案 0 :(得分:112)

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

答案 1 :(得分: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()附加到进程,将调用插入其内存等等来自己做同样的事情,但是这样做非常复杂,不建议使用。

使用适当的权限,执行此操作的其他方法包括查看内核内存,加载内核模块或以其他方式修改内核,但我假设这些都是不可能的。

答案 2 :(得分:2)

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

答案 3 :(得分:2)

你问过bash / python方法。 ulimit将是最好的bash方法(没有手动翻阅/proc/$pid/fd等)。对于python,您可以使用资源模块。

import resource

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

(1024, 65536)

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

答案 4 :(得分: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

输出的格式为文件句柄计数,pid,进程的cm​​ndline

示例输出

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

答案 5 :(得分:0)

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

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

答案 6 :(得分:0)

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

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