私は最近、システムの使用状況を追跡するために開発WebサーバーにMuninをインストールしました。ディスクの使用量がほとんど増加していなくても、システムのiノード使用量が1日あたり約7〜8%増加していることに気付きました。何かが大量の小さなファイルを書き込んでいると思いますが、何が/どこにあるのかわかりません。
ディスク領域の使用状況を見つける方法は知っていますが、iノードの使用状況を要約する方法を見つけることができません。
使用状況のソースを特定できるように、ディレクトリごとにiノードの使用状況を確認する良い方法はありますか?
これがすぐに実行されることを期待しないでください...
多数のiノードがあるサブディレクトリがあると思われるディレクトリにcdします。このスクリプトに非常に時間がかかる場合は、ファイルシステム内のどこを見ればよいでしょうか。/varは良いスタートです...
そうでなければ、そのファイルシステムのトップディレクトリに移動してこれを実行し、それが完了するのを待つと、すべてのiノードを含むディレクトリが見つかります。
find . -type d |
while
read line
do
echo "$( find "$line" -maxdepth 1 | wc -l) $line"
done |
sort -rn | less
ソートのコストは心配していません。私はテストを実行し、350,000のディレクトリに対してソートされていない出力を並べ替えるのに8秒かかりました。最初の発見はかかった。実際のコストは、whileループでこれらすべてのディレクトリを開くことです。 (ループ自体は22秒かかります)。 (テストデータは、350,000のディレクトリを持つサブディレクトリで実行されました。そのうちの1つは100万のファイルを含み、残りは1〜15のディレクトリでした)。
Lsは出力を並べ替えるのでlsはあまり良くないと指摘していました。私はエコーを試しましたが、それも素晴らしいことではありません。他の誰かが、statがこの情報(ディレクトリエントリの数)を提供するが、移植性がないことを指摘しました。 find -maxdepthは、ディレクトリを開くときに非常に高速で、.filesをカウントすることがわかったので、...ここにあります。
問題がファイルが多すぎる1つのディレクトリである場合は、簡単な解決策を次に示します。
# 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つの非常に大きなディレクトリがあり、最初のディレクトリが2番目のディレクトリよりもiノードが1つ多い場合、2番目のディレクトリが表示されないことです。
より完全な解決策は、表示された上位10個の値を追跡し、最後にそれらを出力するよりスマートなPerlスクリプトを記述することです。しかし、それはserverfaultの迅速な回答には長すぎます。
また、中程度にスマートなPerlスクリプトを使用すると、whileループをスキップできます。ほとんどのプラットフォームでは、lsは結果をソートします。これは、大規模なディレクトリの場合にも非常にコストがかかる可能性があります。ここで重要なのは数だけなので、lsソートは必要ありません。
この小さなスニペットを使用できます:
find | cut -d/ -f2 | uniq -c | sort -n
現在のフォルダーの各ディレクトリにあるファイルとディレクトリの数を出力します。一番下に最大の違反者が表示されます。たくさんのファイルがあるディレクトリを見つけるのに役立ちます。 ( 詳細 )
これはあなたの質問への直接の回答ではありませんが、findを使用してサイズが小さい最近変更されたファイルを検索すると、検索が絞り込まれる可能性があります。
find / -mmin -10 -size -20k
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn
lsは、名前がピリオドで始まるファイルを検出しません。 findを使用すると、これを回避できます。これにより、ディレクトリツリー内のすべてのファイルが検索され、各パスの末尾からベース名が削除され、結果の出力に各ディレクトリパスが表示される回数がカウントされます。 「!」を入れなければならない場合がありますシェルが不平を言っている場合は引用符で囲みます。
Iノードは、削除されたが実行中のプロセスによって開いたままにされているファイルによっても使用されます。このMuninパッケージに常に実行されているプログラムが含まれている場合、別のチェック事項は、異常な数のファイルを開いたままにしていないかどうかです。
私はこれをブルートフォースで実行します。ベースラインに対してデバイス全体でtripwireを実行し、しばらくしてからチェックを実行すると、問題のディレクトリが痛い親指のように突き出ます。
(コメントできないのは本当に古くなっています-これはegorgryのためです)
egorgry-ls -iは、iノードCOUNTではなく、エントリのiノードNUMBERを出力します。
ディレクトリ内のファイルで試してみてください-(おそらく)同じ数が表示されますが、これはiノードの数ではなく、単にディレクトリエントリが指すiノードです。
指定されたディレクトリの各子のiノード数を返し、一番下に最大のエントリがある1つのライナー。
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
iノードの使用量は、ファイルまたはディレクトリごとに約1つですよね?そうする
find [path] -print | wc -l
[パス]の下で使用されているiノードの数をおよそ数えます。
効率的なシェルパイプラインを作成しようとしましたが、扱いにくく、遅くなるか不正確になりました。
find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'
1000を超えるファイルが含まれるリーフディレクトリ(およびその他のディレクトリ)をリストします。そこで、時間とRAMの両方で効率的に実行するためのPerlスクリプトを次に示します。出力は
"files-in-subtree""files-directly-in-directory""directory-name"
したがって、上記のsort(1)またはawk(1)などの通常のツールを使用して、簡単にマッサージおよびフィルタリングできます。
#! /usr/bin/Perl -w
# Written by Kjetil Torgrim Homme <[email protected]>
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);