どのディレクトリがすべてのiノードを噛み砕くのかを調べるにはどうすればよいですか?
最終的にはルートディレクトリが最大数のiノードを担当するため、どのような答えが必要か正確にはわかりません。
基本的に、使用可能なiノードが不足しているため、カリングするために不要なディレクトリを見つける必要があります。
あいまいな質問をありがとう。
基本的に、どのディレクトリに多くのファイルがあるかを探していますか?ここに最初の突き刺しがあります:
find . -type d -print0 | xargs -0 -n1 count_files | sort -n
ここで、「count_files」はこれを行うシェルスクリプトです(ありがとうJonathan)
echo $(ls -a "$1" | wc -l) $1
新しいファイルを作成したくない場合(またはiノードを使い果たしたために作成できない場合)、次のクエリを実行できます。
for i in `find . -type d `; do echo `ls -a $i | wc -l` $i; done | sort -n
インサイダーが別の回答で言及したように、再帰的なlsは非常に遅いため、findを使用したソリューションの使用ははるかに高速になります。そのソリューションについては以下を確認してください。 (クレジットが必要な場合はクレジット!)
再帰的lsで提供されるメソッドは非常に遅いです。使用したiノードのほとんどを消費する親ディレクトリをすばやく見つけるためだけに:
cd /partition_that_is_out_of_inodes
for i in *; do echo -e "$(find $i | wc -l)\t$i"; done | sort -n
私は、同僚のジェームズの助けを借りて、次のコードを使用して、1台のマシンで削除する必要があるPHPセッションファイルが大量にあったことを確認しました。
1。いくつのiノードを使用していますか?
root@polo:/# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/xvda1 524288 427294 96994 81% /
none 256054 2 256052 1% /sys/fs/cgroup
udev 254757 404 254353 1% /dev
tmpfs 256054 332 255722 1% /run
none 256054 3 256051 1% /run/lock
none 256054 1 256053 1% /run/shm
none 256054 3 256051 1% /run/user
2。これらのすべてのiノードはどこにありますか?
root@polo:/# find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
[...]
1088 /usr/src/linux-headers-3.13.0-39/include/linux
1375 /usr/src/linux-headers-3.13.0-29-generic/include/config
1377 /usr/src/linux-headers-3.13.0-39-generic/include/config
2727 /var/lib/dpkg/info
2834 /usr/share/man/man3
416811 /var/lib/php5/session
root@polo:/#
最後の行の多くのPHPセッションファイル。
。それらすべてのファイルを削除する方法?
1440分(24時間)より古いディレクトリ内のすべてのファイルを削除します。
root@polo:/var/lib/php5/session# find ./ -cmin +1440 | xargs rm
root@polo:/var/lib/php5/session#
4。動作しましたか?
root@polo:~# find / -xdev -printf '%h\n' | sort | uniq -c | sort -k 1 -n
[...]
1088 /usr/src/linux-headers-3.13.0-39/include/linux
1375 /usr/src/linux-headers-3.13.0-29-generic/include/config
1377 /usr/src/linux-headers-3.13.0-39-generic/include/config
2727 /var/lib/dpkg/info
2834 /usr/share/man/man3
2886 /var/lib/php5/session
root@polo:~# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/xvda1 524288 166420 357868 32% /
none 256054 2 256052 1% /sys/fs/cgroup
udev 254757 404 254353 1% /dev
tmpfs 256054 332 255722 1% /run
none 256054 3 256051 1% /run/lock
none 256054 1 256053 1% /run/shm
none 256054 3 256051 1% /run/user
root@polo:~#
幸いなことに、iノードがほとんど使い果たされたことを通知するsensuアラートがありました。
これは私の考えです。他のものとそれほど違いはありませんが、出力はきれいで、他のもの(ディレクトリとシンボリックリンク)よりも有効なiノードをカウントしていると思います。これは、作業ディレクトリの各サブディレクトリ内のファイルの数をカウントします。出力をソートして2列にフォーマットします。そして、総計( "。"、作業ディレクトリとして表示)を出力します。これはシンボリックリンクをたどりませんが、ドットで始まるファイルとディレクトリをカウントします。これは、デバイスノードと名前付きパイプなどの特殊ファイルをカウントしません。それらもカウントする場合は、「-type l -o -type d -o -type f」テストを削除します。このコマンドは2つの検索コマンドに分割されているため、他のファイルシステムにマウントされているディレクトリを正しく識別することはできません(-mountオプションは機能しません)。たとえば、これは「/ proc」および「/ sys」ディレクトリを実際に無視する必要があります。このコマンドを「/」で実行した場合、「/ proc」と「/ sys」を含めると、総計カウントが大きく歪んでいることがわかります。
for ii in $(find . -maxdepth 1 -type d); do
echo -e "${ii}\t$(find "${ii}" -type l -o -type d -o -type f | wc -l)"
done | sort -n -k 2 | column -t
例:
# cd /
# for ii in $(find -maxdepth 1 -type d); do echo -e "${ii}\t$(find "${ii}" -type l -o -type d -o -type f | wc -l)"; done | sort -n -k 2 | column -t
./boot 1
./lost+found 1
./media 1
./mnt 1
./opt 1
./srv 1
./lib64 2
./tmp 5
./bin 107
./sbin 109
./home 146
./root 169
./dev 188
./run 226
./etc 1545
./var 3611
./sys 12421
./lib 17219
./proc 20824
./usr 56628
. 113207
これを行う簡単なPerlスクリプトを次に示します。
#!/usr/bin/Perl -w
use strict;
sub count_inodes($);
sub count_inodes($)
{
my $dir = shift;
if (opendir(my $dh, $dir)) {
my $count = 0;
while (defined(my $file = readdir($dh))) {
next if ($file eq '.' || $file eq '..');
$count++;
my $path = $dir . '/' . $file;
count_inodes($path) if (-d $path);
}
closedir($dh);
printf "%7d\t%s\n", $count, $dir;
} else {
warn "couldn't open $dir - $!\n";
}
}
Push(@ARGV, '.') unless (@ARGV);
while (@ARGV) {
count_inodes(shift);
}
du
(各ディレクトリカウントにはサブディレクトリの再帰カウントも含まれる)のように動作させる場合は、再帰関数をreturn $count
に変更し、再帰ポイントで次のように言います。
$count += count_inodes($path) if (-d $path);
実際に機能するワンライナー(GNU find、他の種類の検索では、同じFSにとどまるために_-xdev
_と同等の独自のものが必要です)
find / -xdev -type d | while read -r i; do printf "%d %s\n" $(ls -a "$i" | wc -l) "$i"; done | sort -nr | head -10
尾は明らかにカスタマイズ可能です。
ここでの他の多くの提案と同様に、これは各ディレクトリのエントリの量を非再帰的にのみ表示します。
追伸.
高速だが不正確なワンライナー(ディレクトリノードサイズで検出):
_find / -xdev -type d -size +100k
_
for i for dir。[01] do find $ i -printf "%i\n" | sort -u | wc -l | xargs echo $ i- 完了
dir.0-27913
dir.1-27913
つかいます
ncdu -x <path>
次に、Shitf + cを押して、アイテムがファイルのある場所のアイテム数でソートします
Perlスクリプトは優れていますが、シンボリックリンクに注意してください--l filetestがfalseを返す場合にのみ再帰するか、せいぜいオーバーカウント、最悪の場合は無期限に再帰します(これはささいな懸念ではありませんが、サタンの1000年の治世を引き起こす可能性があります)。
ファイルシステムツリー内のiノードをカウントするという考え全体は、ごく一部のファイルへの複数のリンクがある場合にばらばらになります。
これは、現在のディレクトリの下のファイルをカウントします。これは、ファイル名に改行が含まれている場合でも機能するはずです。 GNU=Awk。dの値を変更して、必要な最大の分離されたパスの深さを取得します。0は無制限の深さを意味します。
find . -mount -not -path . -print0 | gawk -v d=2 '
BEGIN{RS="\0";FS="/";SUBSEP="/";ORS="\0"}
{
s="./"
for(i=2;i!=d+1 && i<NF;i++){s=s $i "/"}
++n[s]
}
END{for(val in n){print n[val] "\t" val "\n"}}' | sort -gz -k 1,1
Bash 4と同じ。これは私の経験ではかなり遅いです:
declare -A n;
d=2
while IFS=/ read -d $'\0' -r -a a; do
s="./"
for ((i=2; i!=$((d+1)) && i<${#a[*]}; i++)); do
s+="${a[$((i-1))]}/"
done
((++n[\$s]))
done < <(find . -mount -not -path . -print0)
for j in "${!n[@]}"; do
printf '%i\t%s\n\0' "${n[$j]}" "$j"
done | sort -gz -k 1,1
注:最後にメールスプールディレクトリを見つけて、そこにあるすべてのジャンクを削除したい場合、ファイルが多すぎるとrm *は機能しません。次のコマンドを実行して、そのディレクトリ内のすべてをすばやく削除できます。
*警告*これは、rmが機能しない場合に、すべてのファイルをすばやく削除します
find . -type f -delete
たとえば、ディレクトリサイズを使用して間接的に検索することもできます。
find /path -type d -size +500k
大きなディレクトリがたくさんある場合、500kを増やすことができます。
このメソッドはnot再帰的であることに注意してください。これは、単一のディレクトリに多数のファイルがある場合にのみ役立ちますが、ファイルがその子孫に均等に分散されている場合には役立ちません。