如何确定哪些进程打开了最多的 inode

如何确定哪些进程打开了最多的 inode

这是我的问题,在 munin 图表中可见:

munin inode 图表

我使用的/打开的 inode 数量“突然”不断增加。

有没有办法确定哪个进程正在保留当前打开的 inode?我使用了以下方法https://unix.stackexchange.com/questions/117093/find-where-inodes-are-being-used找到并清理了一些我可以删除的包含邮件和日志的文件夹... 不过,如果 inode 处于 OPEN 状态,那么一定有一些进程在保持它们的使用,对吧? 增加的来源可能不一定是文件最多的文件夹 - 还是我错了?

因此,我想看看是谁在保持开放,然后跟踪使用情况,看看增长来自哪里

更新

根据 Andrew 的脚本,我创建了一个版本,其中还显示进程名称。由于我有一些正在运行的 nginx/apache 进程可能会重新生成,所以我想查看进程名称的结果。

for dir in /proc/*/fd;
do
    echo -n "$dir ";
    pid=`expr "$dir" : '\/proc\/\(.*\)\/.*'`; # extract the pid
    pname=`ps -p $pid -o comm=`; # grab process name
    echo -n "$pname ";
    ls $dir 2>/dev/null | wc -l;
done | sort -n -k 3

示例输出:

/proc/4612/fd sshd 49
/proc/46470/fd node 60
/proc/5655/fd nginx 66
/proc/6656/fd nginx 76
/proc/7654/fd nginx 81
/proc/8578/fd dovecot 107
/proc/9657/fd nginx 117
/proc/3495/fd java 146
/proc/4785/fd mysqld 382

因此,下一个测试将记录一段时间内的分布情况,以查看发生了哪些变化,以及它与 Morgan 提到的 /proc/sys/fs/inode-nr 的数量有何关联

一年之后...

一段时间过去了,这是新的图表 munin 打开 inode

你猜怎么着,9 月底是更换故障驱动器的时间点。因此,看起来整个混乱都是由磁盘错误引起的。尽管如此,这些脚本仍然很有用!

答案1

计算每个目录中的条目数/proc/[PID]/fd。这样您就可以知道每个进程打开的文件描述符数。虽然枚举所有进程需要一段时间,但计数过程中缺少启动或停止的进程应该不是问题,因为您要寻找的是具有大量打开的文件描述符的长寿命进程。

像这样:

for dir in /proc/*/fd;
do
    echo -n "$dir "; #need a space to get real columns for the sort
    ls $dir 2>/dev/null | wc -l;
done | sort -n -k 2

输出的最后几行将显示 /proc/[PID]/fd 目录,其中包含每个进程的打开文件描述符数。罪魁祸首进程应该位于底部附近。

请注意,/proc/[PID]/fd 中的每个条目在技术上都是一个文件描述符,而不是一个单独打开的 inode,每个单独打开的 inode 必须在 /proc/[PID]/fd 目录的某个地方至少有一个单独的文件描述符。

答案2

我认为这里的问题部分在于 munin 所说的“打开 inode”是什么意思。我默认安装的 munin 有两个插件用于获取已分配的 inode 数量:

“/etc/munin/plugins/open_inodes” 从“/proc/sys/fs/inode-nr”获取 inode 指标

“/etc/munin/plugins/df_inode” 从“df -i”的输出中获取指标。

这些数字反映的是现有文件的数量,而不是系统上所有进程正在使用的文件/inode 的数量。

例如,该脚本创建了十个文件,在它终止后,我们可以看到“df -i”和inode-nr中的inode分配都有所增加。

    #!/usr/bin/python

    f0 = open("foo0", "w")
    f1 = open("foo1", "w")
    f2 = open("foo2", "w")
    f3 = open("foo3", "w")
    f4 = open("foo4", "w")
    f5 = open("foo5", "w")
    f6 = open("foo6", "w")
    f7 = open("foo7", "w")
    f8 = open("foo8", "w")
    f9 = open("foo9", "w")

但是,如果我对此进行调整以防止程序终止(并且文件已经存在)......文件将被进程保持“打开”和“正在使用”状态。

    #!/usr/bin/python

    import time

    f0 = open("foo0", "w")
    f1 = open("foo1", "w")
    f2 = open("foo2", "w")
    f3 = open("foo3", "w")
    f4 = open("foo4", "w")
    f5 = open("foo5", "w")
    f6 = open("foo6", "w")
    f7 = open("foo7", "w")
    f8 = open("foo8", "w")
    f9 = open("foo9", "w")

    time.sleep(600)

我们可以在“lsof -p PID”的输出中看到这一点

COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
...
open_some 6602 morgan    3w   REG  254,1        0 262198 /home/morgan/src/foo0
open_some 6602 morgan    4w   REG  254,1        0 262273 /home/morgan/src/foo1
open_some 6602 morgan    5w   REG  254,1        0 262284 /home/morgan/src/foo2
open_some 6602 morgan    6w   REG  254,1        0 262287 /home/morgan/src/foo3
open_some 6602 morgan    7w   REG  254,1        0 262289 /home/morgan/src/foo4
open_some 6602 morgan    8w   REG  254,1        0 262301 /home/morgan/src/foo5
open_some 6602 morgan    9w   REG  254,1        0 262302 /home/morgan/src/foo6
open_some 6602 morgan   10w   REG  254,1        0 262309 /home/morgan/src/foo7
open_some 6602 morgan   11w   REG  254,1        0 262457 /home/morgan/src/foo8
open_some 6602 morgan   12w   REG  254,1        0 268672 /home/morgan/src/foo9

但是我可以根据需要多次运行这个“打开并保持打开”脚本,它不会改变 df/inode-nr 中的数字。

因此,简而言之,munin 报告的是已分配的 inode 数量,而不是所有进程正在使用的所有 inode 数量。如果删除一堆文件后,munin 图表未反映已释放的 inode,则可能只是图表尚未重新生成,或者在所示示例中,图表的时间尺度太长而无法反映突然的变化。

答案3

如果是因为日志文件,则可能是在清理日志文件时没有释放 inode。尝试重新启动打开了这些日志文件的服务,或者在备份要从echo "" > logfilenamegoeshere日志中保存的所有数据后,您也许能够真正清除日志文件而无需重新启动。

答案4

从作者的博客文章可供下载这里。它将显示访问系统上文件的所有进程。

相关内容