Answers:
不要指望它能快速运行...
cd到您怀疑其中可能存在一个包含许多inode的子目录的目录。如果此脚本花费大量时间,您可能已经找到了文件系统中的位置。/ var是一个好的开始...
否则,如果您转到该文件系统中的顶层目录并运行它并等待其完成,则将找到包含所有inode的目录。
find . -type d |
while
read line
do
echo "$( find "$line" -maxdepth 1 | wc -l) $line"
done |
sort -rn | less
我不担心排序的成本。我进行了测试,然后对850,000个目录的未排序输出进行了排序。最初的发现花了。真正的代价是在while循环中打开所有这些目录。(循环本身需要22秒)。(测试数据在包含350,000个目录的子目录上运行,其中一个目录具有一百万个文件,其余目录具有1至15个目录)。
各种各样的人指出ls并不是很好,因为它对输出进行排序。我曾尝试过echo,但这也不是很好。有人指出,stat提供了此信息(目录条目数),但它不是可移植的。事实证明,find -maxdepth在打开目录并计数.file时确实非常快,所以...在这里,这是每个人的要点!
如果问题是一个目录中包含太多文件,那么这是一个简单的解决方案:
# Let's find which partition is out of inodes:
$ df -hi
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/sda3 2.4M 2.4M 0 100% /
...
# Okay, now we know the mount point with no free inodes,
# let's find a directory with too many files:
$ find / -xdev -size +100k -type d
思路find
是,目录的大小与该目录中直接的文件数量成正比。因此,我们在这里查找其中包含大量文件的目录。
如果您不想猜测数字,而是希望列出按“大小”排序的所有可疑目录,这也很容易:
# Remove the "sort" command if you want incremental output
find / -xdev -size +10k -type d -printf '%s %p\n' | sort -n
Grrr,评论需要50代表。因此,此答案实际上是对克里斯答案的评论。
由于发问者可能并不关心所有目录,仅关心最差的目录,因此使用sort可能是非常昂贵的过度杀伤力。
find . -type d |
while
read line
do
echo "$(ls "$line" | wc -l) $line"
done |
perl -a -ne'next unless $F[0]>=$max; print; $max=$F[0]' | less
它不像您的版本那样完整,但是如果行数大于先前的最大值,它会执行打印行,从而大大减少了打印出来的噪音,并节省了分类费用。
不利的一面是,如果您有2个非常大的目录,而第一个恰好比第二个多1个inode,则您将永远看不到第二个。
一个更完整的解决方案是编写一个更智能的perl脚本,该脚本跟踪所看到的前10个值,并在最后输出这些值。但这对于快速的服务器故障答案来说太长了。
另外,一些中度更聪明的perl脚本可以让您跳过while循环-在大多数平台上,ls对结果进行排序,这对于大型目录也可能非常昂贵。ls排序在这里不是必需的,因为我们只关心计数。
这不是您问题的直接答案,但是使用find搜索较小尺寸的最近修改的文件可能会缩小搜索范围:
find / -mmin -10 -size -20k
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn
ls将找不到名称以句点开头的文件。使用find可以避免这种情况。这将在目录树中找到每个文件,在每个路径的末尾标明基本名称,并计算每个目录路径出现在结果输出中的次数。您可能需要输入“!” 如果您的shell抱怨,请用引号引起来。
索引节点还可以被已删除但正在运行的进程保持打开状态的文件用尽。如果此Munin软件包包含任何正在运行的程序,则要检查的另一件事是它是否正在打开异常数量的文件。
我会蛮力地这样做:在整个设备上运行tripwire作为基准,然后过一会儿再执行一次检查,令人讨厌的目录将像拇指酸痛地伸出来。
一种衬里,返回给定目录中每个子项的索引节点计数,其最大条目位于底部。
find . -mindepth 1 -printf "%p/%i\n" \
| awk -F/ '{print $2"/"$NF}' | sort -u \
| cut -d/ -f1 | uniq -c | sort -n
#!/bin/bash
# Show inode distribution for given directory
dirs=$(find $1 -mindepth 1 -maxdepth 1 -type d)
for dir in $dirs
do
inode_count=$(find $dir -printf "%i\n" 2> /dev/null | sort -u | wc -l)
echo "$inode_count $dir"
done
这样运行(假设以上脚本位于工作目录中的可执行文件中)
./indist / | sort -n
我试图编写一个有效的shell管道,但是它变得笨拙,缓慢或不准确,例如,
find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'
将列出其中包含1000多个文件的叶目录(和其他一些目录)。因此,这是一个Perl脚本,可以在时间和RAM上高效地完成此任务。输出就像
«子树中的文件»«目录中的文件直接»«目录名»
因此,您可以使用常规工具(例如上述的sort(1)或awk(1))对其进行轻松按摩和过滤。
#! /usr/bin/perl -w
# Written by Kjetil Torgrim Homme <kjetil.homme@redpill-linpro.com>
use strict;
use File::Find;
my %counted;
my %total;
sub count {
++$counted{$File::Find::dir};
}
sub exeunt {
my $dir = $File::Find::dir;
# Don't report leaf directories with no files
return unless $counted{$dir};
my $parent = $dir;
$parent =~ s!/[^/]*$!!;
$total{$dir} += $counted{$dir};
$total{$parent} += $total{$dir} if $parent ne $dir;
printf("%8d %8d %s\n", $total{$dir}, $counted{$dir}, $dir);
delete $counted{$dir};
delete $total{$dir};
}
die "Usage: $0 [DIRECTORY...]\n" if (@ARGV && $ARGV[0] =~ /^-/);
push(@ARGV, ".") unless @ARGV;
finddepth({ wanted => \&count, postprocess => \&exeunt}, @ARGV);