查找包含大量文件的目录


33

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

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda        2.5M  2.4M   91K   97% /

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

我一直在寻找明显的可疑对象(/var/{log,cache}以及托管所有站点的目录),但是我没有发现任何可疑的东西。我敢肯定,在这头野兽的某个地方,有一个包含数百万个文件的目录。

就上下文而言,繁忙的服务器使用20万个i节点,而我的台式机(旧安装中使用了超过4TB的存储)仅超过一百万。这儿存在一个问题。

所以我的问题是,如何找到问题所在?是否有dufor inode?



1
运行vmstat -1 100并向我们展示其中的一些内容。当心CS(上下文切换)中的大量内容。有时,发生故障的文件系统可能会使许多inode出错。也许合法地,有许多文件。该链接应通知您有关文件和索引节点的信息。stackoverflow.com/questions/653096/howto-free-inode-usage您可能需要使用lsof命令查看正在运行/打开的内容。
j0h 2013年

Answers:


23

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

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

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

我不认为GNU du可以使用多个选项来使每个目录项计数为1。您可以通过使用生成文件列表find并用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"; }'

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


脚本给出错误:awk: line 2: find: regular expression compile failed (bad class -- [], [^] or [) [^ awk: line 2: syntax error at or near ] `/tmp/tmpw99dhs': Permission denied
RaduRădeanu13年

@RaduRădeanu啊,我知道了,我使用了一个怪异的特性,在其他版本中不起作用。我添加了一个反斜杠,根据POSIX,我认为这是必需的。
吉尔(Gilles)“所以,别再邪恶了”

14

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

#!/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

这将按文件计数显示前10个子目录。如果你想有一个顶的X,变化headhead -n x,其中x大于0的自然数。

为了获得100%的肯定结果,请以root特权运行此脚本:

繁忙文件夹


2019年:升起10: read: Illegal option -d...擦洗了-d旗子,read希望不会发生任何不好的事情。当它完成运行时,它将让您知道...
威廉姆斯

3

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

# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail

这将转储整个locate数据库,剥离路径中最后一个“ /”之后的所有内容,然后使用sort和“ uniq -c”获取每个目录的文件/目录数。用管道将“ sort -n”排到尾部,以获取其中包含最多内容的十个目录。


+1:使用locate数据库是一个非常好的主意!
Max Beikirch 2015年

如果由于某种原因无法使用定位,find /path/to/parent -xdev > filelist请先运行,然后直接sed从该列表中读取输入。
Gerrit

1

另一个建议:

http://www.iasptk.com/20314-ubuntu-find-large-files-fast-from-command-line

使用这些搜索来查找服务器上最大的文件。

查找超过1GB的文件

sudo find / -type f -size + 1000000k -exec ls -lh {} \;

查找超过100MB的文件

sudo find / -type f -size + 100000k -exec ls -lh {} \;

查找超过10MB的文件

sudo find / -type f -size + 10000k -exec ls -lh {} \;

第一部分是使用“ -size”标志的find命令,以查找以千字节为单位的不同大小的文件。

最后以“ -exec”开头的最后一位允许指定我们要在找到的每个文件上执行的命令。这里的“ ls -lh”命令包括列出目录内容时看到的所有信息。末尾的h特别有用,因为它以人类可读的格式打印出每个文件的大小。


2
他的问题是inode使用率很高,它指向许多较小的文件,而不是较大的文件。
UpTheCreek

0

当其他人通过外壳在Android上失败时,这对我有用:

find / -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr | head -n25

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.