Итак, мой клиент получил электронное письмо от 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}
и каталог, где размещены все сайты), но я не нахожу ничего действительно подозрительного. Где-то на этом звере я уверен, что есть каталог, который содержит пару миллионов файлов.
Для контекста один мои мои занятые серверы используют 200 тыс. Инодов, а мой рабочий стол (старая установка с более чем 4 ТБ используемого хранилища) составляет чуть более миллиона. Есть проблема.
Итак, мой вопрос, как мне найти, где проблема? Есть ли du
для инодов?
Проверить /lost+found
в случае, если была дисковая проблема, и много спама закончило тем, что было обнаружено как отдельные файлы, возможно неправильно.
Проверить iostat
видеть, производит ли некоторое приложение все еще файлы как сумасшедший.
find / -xdev -type d -size +100k
скажет Вам, если будет каталог, который использует больше чем 100 КБ дискового пространства. Это было бы каталогом, который содержит много файлов или содержал много файлов в прошлом. Можно хотеть скорректировать число размера.
Я не думаю, что существует комбинация опций к GNU du
сделать это количеством 1 на запись каталога. Можно сделать это путем создания списка файлов с find
и делая определенный подсчет в awk. Вот a du
для inodes. Минимально протестированный, не пытается справиться с именами файлов, содержащими новые строки.
#!/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
скажет Вам крупнейших преступников.
Это сработало для меня, когда другой не удалось на Android через оболочку:
find / -type d -exec sh -c "fc=\$(find '{}' -type f | wc -l); echo -e \"\$fc\t{}\"" \; | sort -nr | head -n25
Другой предлагает:
http://www.iasptk.com/20314-ubuntu-find-large-files-fast-from-command-line
Используйте эти поиски для нахождения самых больших файлов на сервере.
Найдите файлы более чем 1 ГБ
sudo находят / - тип f - размер +1000000k - должностное лицо ls - люфтганза {} \;
Найдите файлы более чем 100 МБ
sudo находят / - тип f - размер +100000k - должностное лицо ls - люфтганза {} \;
Найдите файлы более чем 10 МБ
sudo находят / - тип f - размер +10000k - должностное лицо ls - люфтганза {} \;
Первая часть является командой находки с помощью "-размер" флаг для нахождения файлов свыше различных размеров измеряемыми в килобайтах.
Последнее обдумало конец, запускающийся с "-должностное лицо" позволяет указывать команду, которую мы хотим выполнить на каждом файле, который мы находим. Здесь "ls - люфтганза" управляют для включения всей информации, видящей при списке содержания каталога. H к концу особенно полезен, поскольку он распечатывает размер каждого файла в человекочитаемом формате.
Мне нравится использовать что-то вроде du --inodes -d 1
, чтобы найти каталог, который либо рекурсивно, либо напрямую содержит много файлов.
Мне также нравится этот ответ: https://unix.stackexchange.com/a/123052
Для ленивых из нас вот суть этого:
blockquote>du --inodes -S | sort -rh | sed -n \ '1,50{/^.\{71\}/s/^\(.\{30\}\).*\(.\{37\}\)$/\1...\2/;p}'
Можно свериться с этим сценарием:
#!/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:
Часто быстрее, чем поиск, если ваша база данных locate обновлена:
# locate '' | sed 's|/[^/]*$|/|g' | sort | uniq -c | sort -n | tee filesperdirectory.txt | tail
Это выдает всю базу данных locate, удаляет все, что находится за последним символом / в пути, затем сортирует и "uniq -c" выдает количество файлов / каталогов на один каталог. «sort -n» отправляется в хвост, чтобы получить десять каталогов с наибольшим количеством вещей в них.
немного старая тема, но интересная, поэтому предлагаю свои решения.
Первый использует несколько команд, передаваемых по конвейеру, и находит каталоги с более чем 1000 файлами внутри:
find / -type d |awk '{print "echo -n "$0" ---- ; ls -1 "$0" |wc -l "}'|bash |awk -F "----" '{if ($2>1000) print $1}'
Второй простой. Просто попробуйте найти каталоги размером более 4096 байт. Обычно пустой каталог имеет размер 4096 байт в файловой системе ext4 и 6 байт в xfs:
find / -type d -size +4096c
Вы, конечно, можете изменить это, но я считаю, что в большинстве случаев это должно работать с таким значением.