Назад | Перейти на главную страницу

Определите место использования Inode

Недавно я установил 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 инодов.