Визначте місце використання Inode


15

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

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

Чи є хороший спосіб визначити використання inode за каталогом, щоб я міг знайти джерело використання?

Відповіді:


15

Не чекайте, що це швидко запуститься ...

cd в каталог, де ви підозрюєте, що може бути підкаталог з великою кількістю входів. Якщо цей сценарій займає величезну кількість часу, ви, швидше за все, знайшли, де у файловій системі шукати. / 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 дає цю інформацію (кількість записів у каталозі), але вона не є портативною. Виявляється, пошук -maxdepth дуже швидкий при відкритті каталогів і підраховує .файли, так що ... ось він .. очки для всіх!


2
@mike G: Ви на 100% вірні, що це не найшвидший спосіб зробити подібне. На мій погляд, правильний спосіб її оптимізації - це перенаправлення на stderr при запуску та завершенні частини сценарію «підрахунок записів до каталогу». Таким чином, коли ви потрапите в каталог з мільйонами записів, він скаже «обробка котушки каталогу / postfix / maildrop», а потім не скаже миттєво «закінчено» і бум - подивіться у spool / postfix / maildrop, і ви побачите багато файли.
chris

Я також не хвилювався за вартість сортування, оскільки це разова або, принаймні, досить нечаста задача.
Дейв Forgac

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-й, 2-го ви ніколи не побачите.

Більш повним рішенням було б написати розумніший сценарій perl, який відслідковує 10 найпопулярніших значень та виводить їх у кінці. Але це занадто довго для швидкої відповіді сервера за замовчуванням.

Крім того, деякі з розумніших сценаріїв perl дозволять вам пропустити цикл часу - на більшості платформ ls сортує результати, і це також може бути дуже дорогим для великих каталогів. Сортування ls тут не потрібне, оскільки все, що нас хвилює, - це кількість.


1
Правда щодо ls - у таких ситуаціях я більше переживаю, щоб було зрозуміло, що я роблю, і не стільки щодо виступу. Я майже впевнений, що ви можете використовувати echo $ line / * | wc -w замість ls $ line | wc -l, і ви уникнете проблеми сортування ls.
chris

Я щойно провів тест на каталог з мільйоном файлів, а ls зайняв 22 секунди, а echo * зайняло 12 секунд. (Для запису, echo * в оболонці не досягне межі аргументу, оскільки відлуння в 99% снарядів при активному використанні є вбудованим)
chris

ls -f не буде сортувати результати. Сортування результатів каталогів призводить до поширеної проблеми з NFS та великими каталогами. Якщо час для читання та сортування каталогу (на сервері) перевищує час очікування NFS, каталог та підкаталоги непридатні.
mpez0

5

Ви можете використовувати цей маленький фрагмент:

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

Він надрукує, скільки файлів і каталогів є у кожному з каталогів у поточній папці, з найбільшими правопорушниками внизу. Це допоможе вам знайти каталоги, у яких багато файлів. ( детальніше )


Це спрацювало блискуче.
птман

3

Це не прямий відповідь на ваше запитання, але пошук нещодавно змінених файлів невеликого розміру за допомогою значка пошуку може звузити ваш пошук:

find / -mmin -10 -size -20k

3
find /path ! -type d | sed 's,/[^/]*$,,' | uniq -c | sort -rn

Ls не шукатиме файли, імена яких починаються з періоду. Використання знахідки уникає цього. Це знаходить кожен файл у дереві каталогів, відтинає базове ім’я з кінця кожного шляху і підраховує кількість разів, де кожен шлях до каталогу з'являється в отриманому результаті. Можливо, вам доведеться поставити "!" у лапках, якщо ваша оболонка скаржиться на це.

Вставки також можуть бути використані файлами, які були видалені, але відкриті за допомогою запущеного процесу. Якщо цей пакунок Munin включає в себе будь-які постійно працюючі програми, ще одна річ, щоб перевірити, чи він містить відкриту незвичну кількість файлів.


Вставки можна також взяти з по-справжньому глибоких каталогів, яких це не знайде. У цьому є ряд дивних випадків, але найпоширеніша ситуація - це каталог, повний файлів із звичайними іменами.
chris

3

Я б грубо змусив цей: запустіть тривимірний провід на всьому пристрої за базовою лінією, а потім запустіть перевірку через деякий час, і каталог, який образить, буде стирчати, як біль.


На це, ймовірно, знадобиться мільярд років. Швидше зробити, це запустити lsof | grep DIR та знайдіть у кожному з цих каталогів багато нових файлів.
chris

2
Добре, як щодо цього: знайти / | сортувати> /tmp/find1.txt; знайти / | сортувати> /tmp/find2.txt; diff /tmp/find1.txt /tmp/find2.txt
Джефф Фріц

2

(не в змозі коментувати дійсно старіє - це для egorgry)

egorgry - ls -i друкує inode NUMBER для запису, а не inode COUNT.

Спробуйте це з файлом у вашому каталозі - ви, мабуть, побачите однаково високе число, але це не кількість підрахунків, це лише вкладка #, на яку вводяться точки вашого каталогу.


Лол. Я проголосував за тебе одного. Дякую за пояснення. використання inode завжди бентежить.
egorgry

дякую Тепер я боюся перетворити це на коментар до вашого вузла, якщо я втрачу карму, коли видаляю цю відповідь :)
Майк Г.

2

Оновлення

Один вкладиш, який повертає кількість 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

1

використання inode - це приблизно одне на файл або каталог, правда? То роби

find [path] -print | wc -l

підрахувати приблизно, скільки вкладень використовується під [шлях].


1

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

find . -depth -printf '%h\n' | uniq -c | awk '$1>1000'

перелічить каталоги листів (та деякі інші) з більш ніж 1000 файлами в них. Отже, ось сценарій Perl, щоб зробити це ефективно і в часі, і в оперативній пам'яті. Вихід такий

«Файли-піддерево» «Файли-безпосередньо-в-каталозі» «Ім'я-каталог»

тож ви можете легко масажувати і фільтрувати його за допомогою звичайних інструментів, наприклад, сортувати (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 введення.


3
ls -i друкує вхідний NUMBER для запису, а не inode COUNT. Спробуйте це з файлом у вашому каталозі - ви, мабуть, побачите однаково високе число, але це не кількість підрахунків, це лише вкладення # у ваш пункт входу до каталогу.
egorgry
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.