这是我的问题,在 munin 图表中可见:
我使用的/打开的 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 的数量有何关联
一年之后...
你猜怎么着,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
日志中保存的所有数据后,您也许能够真正清除日志文件而无需重新启动。