Недавно я установил Munin на веб-сервер разработки, чтобы отслеживать использование системы. Я заметил, что использование inode системой увеличивается примерно на 7-8% в день, хотя использование диска почти не увеличилось. Я предполагаю, что что-то пишет тонну крошечных файлов, но я не могу найти что / где.
Я знаю, как узнать использование дискового пространства, но не могу найти способ обобщить использование inode.
Есть ли хороший способ определить использование inode по каталогу, чтобы я мог найти источник использования?
Не ждите, что это пойдет быстро ...
cd в каталог, в котором, как вы подозреваете, может быть подкаталог с большим количеством inodes. Если этот сценарий занимает много времени, вы, вероятно, нашли, где искать в файловой системе. / var - хорошее начало ...
В противном случае, если вы перейдете в верхний каталог в этой файловой системе, запустите его и дождетесь завершения, вы найдете каталог со всеми индексными дескрипторами.
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 до 15 каталогов).
Различные люди указывали, что ls не очень хорош в этом, потому что он сортирует вывод. Я пробовал эхо, но это тоже не очень хорошо. Кто-то еще указал, что stat дает эту информацию (количество записей в каталоге), но она не переносима. Оказывается, find -maxdepth действительно быстро открывает каталоги и считает. Файлы, так что ... вот оно ... баллы для всех!
Если проблема в одном каталоге со слишком большим количеством файлов, вот простое решение:
# 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
Гррр, для комментирования нужно 50 реп. Итак, этот ответ на самом деле является комментарием к ответу Криса.
Поскольку спрашивающего, вероятно, не интересуют все каталоги, а только худшие, то использование сортировки, вероятно, будет очень дорогостоящим излишеством.
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 больше, чем во втором, вы никогда не увидите второй.
Более полным решением было бы написать более умный скрипт на Perl, который отслеживает 10 самых популярных значений и выводит их в конце. Но это слишком долго для быстрого ответа на ошибку сервера.
Кроме того, некоторые более умные сценарии 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 не найдет файлы, имена которых начинаются с точки. С помощью найти избегает этого. Это находит каждый файл в дереве каталогов, отсекает базовое имя в конце каждого пути и подсчитывает, сколько раз каждый путь к каталогу появляется в результирующем выводе. Возможно, вам придется поставить знак "!" в кавычках, если ваша оболочка на это жалуется.
Inodes также могут использоваться файлами, которые были удалены, но остаются открытыми запущенным процессом. Если этот пакет Munin включает какие-либо постоянно работающие программы, еще одна вещь, которую нужно проверить, - это то, что в нем открыто необычное количество файлов.
Я бы использовал грубую силу: запустите tripwire на всем устройстве для определения базового уровня, затем запустите проверку через некоторое время, и проблемный каталог будет торчать, как больной палец.
(отсутствие возможности комментировать действительно стареет - это для эгоизма)
egorgry - ls -i печатает НОМЕР индексного дескриптора для записи, а не СЧЁТ ИНода.
Попробуйте это с файлом в вашем каталоге - вы (вероятно) увидите такое же большое число, но это не количество inodes, это просто индекс #, на который указывает ваша запись в каталоге.
Один лайнер, который возвращает количество inode каждого дочернего элемента данного каталога с самыми большими записями внизу.
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
Использование inode примерно по одному на файл или каталог, верно? Ну действуй
find [path] -print | wc -l
чтобы приблизительно подсчитать, сколько inodes используется в [path].
Я пытался написать эффективный конвейер оболочки, но он стал громоздким, медленным или неточным, например,
find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'
отобразит конечные каталоги (и некоторые другие), в которых содержится более 1000 файлов. Итак, вот сценарий Perl, который делает это эффективно как по времени, так и по оперативной памяти. Выход похож на
«Файлы-в-поддереве» «файлы-непосредственно в-каталоге» «имя-каталога»
так что вы можете легко его массировать и фильтровать с помощью обычных инструментов, например, 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);
[gregm@zorak2 /]$ ls -i /home 131191 gregm
у меня дома на ноутбуке используется 131191 инодов.