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

15

Недавно я установил Munin на веб-сервере разработки, чтобы отслеживать использование системы. Я заметил, что использование системного инода увеличивается примерно на 7-8% в день, хотя использование диска практически не увеличивается. Я предполагаю, что что-то пишет тонна крошечных файлов, но я не могу найти что / где.

Я знаю, как найти использование дискового пространства, но я не могу найти способ суммировать использование inode.

Есть ли хороший способ определить использование inode по каталогу, чтобы я мог найти источник использования?

Дейв Форгак
источник

Ответы:

15

Не ожидайте, что это будет быстро ...

Перейдите в каталог, в котором, как вы подозреваете, может быть подкаталог с большим количеством inode. Если этот сценарий занимает много времени, вы, вероятно, нашли, где искать в файловой системе. / VAR хорошее начало ...

В противном случае, если вы перейдете в верхний каталог в этой файловой системе и запустите его и дождетесь его завершения, вы найдете каталог со всеми inode.

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 действительно быстро открывает каталоги и считает .files, так что ... вот оно ... очки для всех!

Крис
источник
2
@mike G: Вы на 100% правы, что это не самый быстрый способ сделать подобные вещи. На мой взгляд, правильный способ оптимизировать это - перенаправить на stderr при запуске и завершении части скрипта «считать записи каталога». Таким образом, когда вы попадаете в каталог с миллионом записей, он говорит «обработка каталога spool / postfix / maildrop», а затем не сразу говорит «закончено» и boom - посмотрите в spool / postfix / maildrop, и вы увидите много файлы.
Крис
Я также не беспокоился о стоимости сортировки, так как это одноразовая или, по крайней мере, довольно редкая задача.
Дэйв Форгак
7

Если проблема в одном каталоге со слишком большим количеством файлов, вот простое решение:

# 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
Денилсон Са Майя
источник
6

Grrr, комментирование требует 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 больше инода, чем вторая, вы никогда не увидите 2-ю.

Более полное решение будет состоять в том, чтобы написать более умный Perl-скрипт, который отслеживает 10 лучших значений и выводит их в конце. Но это слишком долго для быстрого ответа о сбое сервера.

Кроме того, некоторые более умные сценарии на Perl позволят вам пропустить цикл while - на большинстве платформ ls сортирует результаты, что также может быть очень дорого для больших каталогов. Сортировка ls здесь не обязательна, так как все, что нас интересует - это количество.

Майк Г.
источник
1
Правда в отношении ls - в подобных ситуациях я больше беспокоюсь о том, что мне ясно, что я делаю, а не о производительности. Я уверен, что вы можете использовать echo $ line / * | wc -w вместо строки ls $ | wc -l и вы избежите проблемы с сортировкой ls.
Крис
Я только что проверил каталог с миллионами файлов, ls занял 22 секунды, а echo * - 12 секунд. (Для записи, echo * в оболочке не достигнет предела arg, потому что echo в 99% оболочек при активном использовании является встроенным)
Крис
ls -f не будет сортировать результаты. Сортировка результатов каталогов приводит к общей проблеме с NFS и большими каталогами. Если время чтения и сортировки каталога (на сервере) превышает время ожидания NFS, каталог и подкаталоги не могут использоваться.
mpez0
5

Вы можете использовать этот маленький фрагмент:

find | cut -d/ -f2 | uniq -c | sort -n

Он распечатает, сколько файлов и каталогов находится в каждом из каталогов в текущей папке, с самыми большими нарушителями внизу. Это поможет вам найти каталоги, которые имеют много файлов. ( больше информации )

Рори
источник
Это сработало блестяще.
Птман
3

Это не прямой ответ на ваш вопрос, но поиск недавно измененных файлов небольшого размера с помощью команды find может сузить область поиска:

find / -mmin -10 -size -20k
Кайл Брандт
источник
3
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn

ls не найдет файлы, имена которых начинаются с точки. Использование find позволяет избежать этого. Он находит каждый файл в дереве каталогов, отбрасывает базовое имя с конца каждого пути и подсчитывает, сколько раз каждый путь каталога появляется в результирующем выводе. Возможно, вам придется поставить "!" в кавычках, если ваша оболочка жалуется на это.

Иноды могут также использоваться файлами, которые были удалены, но которые остаются открытыми в процессе работы. Если этот пакет Munin содержит какие-либо постоянно работающие программы, еще одна вещь, чтобы проверить, является ли он открытым необычное количество файлов.

Kenster
источник
Иноды также могут быть взяты из очень глубоких каталогов, которые не найдутся. В этом есть ряд странных крайних случаев, но наиболее распространенная ситуация - это каталог, полный файлов с обычными именами.
Крис
3

Я бы использовал этот метод грубо: запустил tripwire на всем устройстве для базовой линии, затем через некоторое время запустил проверку, и каталог-нарушитель вылезет, как больной большой палец.

Джефф Фриц
источник
Это, вероятно, займет миллиард лет. Быстрее всего запустить lsof | grep DIR и посмотрите в каждом из этих каталогов множество новых файлов.
Крис
2
Хорошо, как насчет этого: найти / | sort> /tmp/find1.txt; найти / | sort> /tmp/find2.txt; diff /tmp/find1.txt /tmp/find2.txt
Джефф Фриц,
2

(неумение комментировать действительно стареет - это для egorgry)

egorgry - ls -i печатает индекс NODBER для записи, а не индекс COUNT.

Попробуйте это с файлом в вашем каталоге - вы (вероятно) увидите такое же большое число, но это не количество инодов, это просто инод #, на который указывает ваша запись в каталоге.

Майк Г.
источник
лол. Я проголосовал за тебя один. Спасибо за объяснение. использование inode всегда сбивало с толку.
egorgry
спасибо Теперь я боюсь преобразовать это в комментарий к вашему узлу, на случай, если я потеряю карму при удалении этого ответа :)
Майк Дж
2

Обновить

Один вкладыш, который возвращает количество инодов для каждого дочернего элемента данного каталога с самыми большими записями внизу.

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
raphinesse
источник
1

Использование Inode составляет примерно один на файл или каталог, верно? Ну действуй

find [path] -print | wc -l

приблизительно посчитать, сколько inode используется в [path].

pjz
источник
1

Я пытался написать эффективный конвейер оболочки, но он стал громоздким и либо медленным, либо неточным, например,

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);

источник
-1
[gregm@zorak2 /]$ ls -i /home
131191 gregm

мой дом на моем ноутбуке использует 131191 инодов.

egorgry
источник
3
ls -i печатает ИНДЕКС ИНОДА для записи, а не ИНОД ИНДЕКСА. Попробуйте это с файлом в вашем каталоге - вы (вероятно) увидите такое же большое число, но это не количество инодов, это просто инод #, на который указывает ваша запись в каталоге.
egorgry