查找包含大量文件的目录

Oli*_*Oli 34 filesystem inode

所以我的一个客户今天收到了一封来自 Linode 的电子邮件,说他们的服务器导致 Linode 的备份服务崩溃。为什么?文件太多。我笑了,然后跑了:

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda        2.5M  2.4M   91K   97% /
Run Code Online (Sandbox Code Playgroud)

废话。240 万个 inode 正在使用中。这到底是怎么回事?!

我已经寻找了明显的嫌疑人(/var/{log,cache}以及托管所有站点的目录),但我没有发现任何真正可疑的东西。我确信在这个野兽的某个地方有一个包含几百万个文件的目录。

上下文一个我繁忙的服务器使用200K的inode和我的桌面(旧安装超过二手储存4TB)只是刚刚超过一百万。有一个问题。

所以我的问题是,我如何找到问题所在?有du用于 inode 吗?

Gil*_*il' 25

检查是否/lost+found存在磁盘问题并且许多垃圾最终被检测为单独的文件,可能是错误的。

检查iostat是否某些应用程序仍在疯狂地生成文件。

find / -xdev -type d -size +100k会告诉您是否存在使用超过 100kB 磁盘空间的目录。那将是一个包含大量文件的目录,或者过去包含大量文件的目录。您可能需要调整尺寸图。

我认为 GNU 没有组合选项du可以使其每个目录条目数为 1。您可以通过使用findawk生成文件列表并在 awk 中进行一些计数来完成此操作。这是一个du用于 inode 的。最少测试,不会尝试处理包含换行符的文件名。

#!/bin/sh
find "$@" -xdev -depth | awk '{
    depth = $0; gsub(/[^\/]/, "", depth); depth = length(depth);
    if (depth < previous_depth) {
       # A non-empty directory: its predecessor was one of its files
       total[depth] += total[previous_depth];
       print total[previous_depth] + 1, $0;
       total[previous_depth] = 0;
    }
    ++total[depth];
    previous_depth = depth;
}
END { print total[0], "total"; }'
Run Code Online (Sandbox Code Playgroud)

用法:du-inodes /。递归打印非空目录列表及其子目录中的条目总数。将输出重定向到一个文件并在您空闲时查看它。sort -k1nr <root.du-inodes | head会告诉你最大的罪犯。


Rad*_*anu 15

您可以使用此脚本进行检查:

#!/bin/bash

if [ $# -ne 1 ];then
  echo "Usage: `basename $0` DIRECTORY"
  exit 1
fi

echo "Wait a moment if you want a good top of the bushy folders..."

find "$@" -type d -print0 2>/dev/null | while IFS= read -r -d '' file; do 
    echo -e `ls -A "$file" 2>/dev/null | wc -l` "files in:\t $file"
done | sort -nr | head | awk '{print NR".", "\t", $0}'

exit 0
Run Code Online (Sandbox Code Playgroud)

这将按文件计数打印前 10 个子目录。如果你想要一个顶部 x,改变headhead -n x,其中x是一个大于 0 的自然数。

对于 100% 确定的结果,请使用 root 权限运行此脚本:

顶级文件夹


小智 6

如果您的定位数据库是最新的,通常比查找更快:

# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail
Run Code Online (Sandbox Code Playgroud)

这会转储整个定位数据库,删除路径中最后一个“/”之后的所有内容,然后排序和“uniq -c”获取每个目录的文件/目录数。“sort -n”通过管道连接到 tail 以获得包含最多内容的十个目录。