Найти каталоги с большим количеством файлов в


33

Итак, мой клиент получил электронное письмо от Linode сегодня, в котором говорилось, что его сервер приводит к взрыву службы резервного копирования Linode. Зачем? Слишком много файлов. Я засмеялся и побежал:

# df -ih
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda        2.5M  2.4M   91K   97% /

Дерьмо. 2,4 миллиона Inode в использовании. Что, черт возьми, происходит ?!

Я искал очевидных подозреваемых ( /var/{log,cache}и каталог, в котором размещены все сайты), но я не нахожу ничего действительно подозрительного. Где-то на этом звере я уверен, что есть каталог, который содержит пару миллионов файлов.

Для первого контекста мои занятые серверы используют 20000 инодов, а мой рабочий стол (старая установка с более чем 4 ТБ использованного хранилища) составляет чуть более миллиона. Существует проблема.

Итак, мой вопрос, как мне найти, где проблема? Есть ли duдля inode?



1
запустите vmstat -1 100 и покажите нам что-нибудь из этого. остерегайтесь большого числа в CS (переключение контекста). Иногда отказывающая файловая система может потерять много inode для ошибок. Или, возможно, законно, есть много файлов. Эта ссылка должна информировать вас о файлах и инодах. stackoverflow.com/questions/653096/howto-free-inode-usage вам может понадобиться узнать, что запущено / открыто с помощью команды lsof.
13

Ответы:


23

Проверьте, не /lost+foundвозникла ли проблема с диском и обнаружилось ли много ненужных файлов в виде отдельных файлов, возможно, неправильно.

Проверьте, не iostatгенерирует ли какое-либо приложение файлы типа сумасшедшие.

find / -xdev -type d -size +100kскажет вам, если есть каталог, который использует более 100 КБ дискового пространства. Это будет каталог, который содержит много файлов или содержит много файлов в прошлом. Вы можете настроить размер фигуры.

Я не думаю, что есть комбинация опций для GNU, duчтобы она считала 1 на каждую запись каталога. Вы можете сделать это, создав список файлов с помощью findи немного посчитав в awk. Вот duдля иноды. Минимально протестировано, не пытается справиться с именами файлов, содержащими переводы строк.

#!/bin/sh
find "$@" -xdev -depth | awk '{
    depth = $0; gsub(/[^\/]/, "", depth); depth = length(depth);
    if (depth < previous_depth) {
       # A non-empty directory: its predecessor was one of its files
       total[depth] += total[previous_depth];
       print total[previous_depth] + 1, $0;
       total[previous_depth] = 0;
    }
    ++total[depth];
    previous_depth = depth;
}
END { print total[0], "total"; }'

Использование: du-inodes /. Печатает список непустых каталогов с рекурсивным общим количеством записей в них и их подкаталогах. Перенаправьте вывод в файл и просмотрите его на досуге. sort -k1nr <root.du-inodes | headскажу вам самые большие обидчики.


Сценарий awk: line 2: find: regular expression compile failed (bad class -- [], [^] or [) [^ awk: line 2: syntax error at or near ] `/tmp/tmpw99dhs': Permission denied
выдает

@ RaduRădeanu Ах, я вижу, я использовал особенность gawk, которая не работает в других версиях. Я добавил обратную косую черту, которая я считаю необходимой в соответствии с POSIX.
Жиль "ТАК - перестань быть злым"

14

Вы можете проверить с помощью этого скрипта:

#!/bin/bash

if [ $# -ne 1 ];then
  echo "Usage: `basename $0` DIRECTORY"
  exit 1
fi

echo "Wait a moment if you want a good top of the bushy folders..."

find "$@" -type d -print0 2>/dev/null | while IFS= read -r -d '' file; do 
    echo -e `ls -A "$file" 2>/dev/null | wc -l` "files in:\t $file"
done | sort -nr | head | awk '{print NR".", "\t", $0}'

exit 0

Это печатает 10 лучших подкаталогов по количеству файлов. Если вы хотите верхний x, измените headна head -n x, где xнатуральное число больше 0.

Для 100% уверенного результата запустите этот скрипт с привилегиями root:

топ-кустарниковая-папка


2019: поднял 10: read: Illegal option -d... вычистил -dфлаг, readнадеясь, что ничего плохого не случится. Даст вам знать, когда он закончит работу ...
Уильямс

3

Часто быстрее, чем найти, если база данных locate обновлена:

# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail

Это сбрасывает всю базу данных locate, удаляет все, что находится за последним символом '/' в пути, затем сортировка и "uniq -c" дают вам количество файлов / каталогов на каталог. "sort -n" отправляется в хвост, чтобы получить десять каталогов с наибольшим количеством вещей в них.


+1: использование базы данных locate - очень хорошая идея!
Макс Бейкирх

Если по какой-либо причине вы не можете использовать locate, find /path/to/parent -xdev > filelistсначала запустите, а затем направьте sed для чтения ввода из этого списка.
геррит

1

Еще предлагаю:

http://www.iasptk.com/20314-ubuntu-find-large-files-fast-from-command-line

Используйте эти поиски, чтобы найти самые большие файлы на вашем сервере.

Найти файлы размером более 1 ГБ

sudo find / -type f -size + 1000000k -exec ls -lh {} \;

Найти файлы размером более 100 МБ

sudo find / -type f -size + 100000k -exec ls -lh {} \;

Найти файлы размером более 10 МБ

sudo find / -type f -size + 10000k -exec ls -lh {} \;

Первая часть - это команда find, использующая флаг «-size» для поиска файлов разных размеров, измеряемых в килобайтах.

Последний бит в конце, начинающийся с «-exec», позволяет указать команду, которую мы хотим выполнить для каждого найденного файла. Здесь команда "ls -lh" включает всю информацию, отображаемую при выводе содержимого каталога. Буква h в конце особенно полезна, поскольку она печатает размер каждого файла в удобочитаемом формате.


2
Его проблема заключается в большом использовании inode, что указывает на множество небольших файлов, а не больших.
UpTheCreek,

0

Это сработало для меня, когда другой не удалось на Android через оболочку:

find / -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr | head -n25

0

Мне нравится использовать что-то вроде du --inodes -d 1поиска каталога, который либо рекурсивно, либо напрямую содержит много файлов.

Мне также нравится этот ответ: https://unix.stackexchange.com/a/123052

Для ленивых из нас вот суть этого:

du --inodes -S | sort -rh | sed -n \
    '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.