Так и не смог придумать нормальный заголовок, так что суть — в следующем абзаце.
Нередко случается такое, что приложение говорит «cannot write blah to hdd, not enough space», хотя df -h говорит, что места ещё дохрена. Неопытный админ начинает задумчиво чесать репу, удивляться, гуглить и тд.
Чаще всего такое поведение случается в трех случаях:
0) вы не туда смотрите df-ом
1) кончились inodes на диске
2) какой-то из демонов держит удаленные файлы.
Давайте поподробнее. Про нулевой случай всё понятно — приложение пытается записать в /var, он у вас смонтирован отдельным разделом, а вы смотрите на место в корне. Или такая же фигня с каким-нибудь /dev/shm, /run или любым другим tmpfs. В том числе и с самим /tmp — он из-за разных глюков может смонтироваться с размером в несколько килобайт.
Also, «не туда» может возникнуть по причине того, что вы смонтировали новый раздел в не пустой каталог. Например, у вас стало заканчиваться место в /var, вы подключили новый hdd, скопировали всё, смонтировали новый hdd в /var. Логично, что место в «старом» /var (который был частью корневого раздела и ею остаётся на физическом уровне) не освободится и вы никак не узнаете, что у вас там лежит ещё 50 гб хлама, который вы не сможете увидеть, пока не отмонтируете новый /var и не удалите файлы явно.
Про inodes тоже понятно. Если у вас много-много мелких файлов, то inodes будут кончаться сильно быстрее, чем место на диске. Каждый файл будет кушать хотя бы одну inode. Если количество inodes меньше, чем блоков на диске — то они закончатся быстрее, чем свободное место (т.е. блоки).
Починить на лету это сложно (ну кроме как удалением той самой кучи мелких файлов). На типовом стеке LAMP-ы это случается чаще всего из-за файлов сессий (если вы их вынесли куда то из /var/lib/php5 и не настроили чистку нового каталога по крону) или из-за битриксов — небольшой сайт на битриксе с включенным кешированием скушает вам 300-400k inodes (а на digitalocean вам на виртуалке за 5 баксов дают 2kk inodes). Большой сайт на битриксе влегкую кушает 2-3kk inodes и не давится.
Проверить, сколько у вас inodes свободно можно командой df -i:
Filesystem Inodes IUsed IFree IUse% Mounted on
rootfs 1966080 1966079 1 100% /
...
IFree — целая одна. Нужно чистить (удалять мелкие файлы). Ну или просто большие файлы, но это будет куда менее эффективно.
Ну и второй вариант — самый непонятный. df говорит, что места нет, df -i говорит, что inodes есть, du -h / говорит, что файлы занимают меньше половины всего места, блаблабла, куда делось место — непонятно. Возможная причина — ниже.
Когда вы удаляете файлы, используемый в данный момент запущенным приложением, файл не удаляется вообще — только стирается его inode и файл больше не видно в ls. То есть, если вы удалите 100G-овый /var/log/syslog не останавливая syslog — то место не освободится, а syslog продолжит писать в файл по старому адресу (при этом посмотреть этот файл штатными средствами системы вы уже не сможете, так как ни один новый процесс уже не сможет обратиться к этому файлу).
Проверяется такое очень легко — командой lsof | grep deleted:
syslog-ng 196 root 14w REG 252,2 8082186240 1704154 /var/log/syslog (deleted)
syslog-ng 196 root 20w REG 252,2 14302392320 1708519 /var/log/mail.log (deleted)
syslog-ng 196 root 25w REG 252,2 14302023680 1708509 /var/log/mail.info (deleted)
syslog-ng 196 root 26w REG 252,2 14301499392 1709839 /var/log/mail.warn (deleted)
mysqld 582 mysql 4u REG 252,2 0 1707925 /tmp/ib9mkQir (deleted)
mysqld 582 mysql 5u REG 252,2 215 1708488 /tmp/ib5CiO9t (deleted)
mysqld 582 mysql 6u REG 252,2 0 1709769 /tmp/ibLxoM0w (deleted)
mysqld 582 mysql 7u REG 252,2 0 1709868 /tmp/ibRdFsTz (deleted)
mysqld 582 mysql 11u REG 252,2 0 1709877 /tmp/ibJklN0D (deleted)
Здесь мы хорошо видим, что файлы, которые используют syslog-ng и mysqld, удалили, но демоны всё ещё висят над этими файлами и пишут в них.
«Починить место» в данном случае можно так:
Само собой, если у вас там другие процессы в первом столбце — то перезапускать нужно их.
Лучше не «restart», а явно «stop» и «start» выполнять — не всегда при перезапуске демон полностью завершается…
Да, для апстарта так разумнее делать. Чего то я забыл про него.
Еще можно:
1) В выводе lsof посмотреть pid процесса и имя файла
2) Пойди в /proc/PID/fd, сказать «ls -la», увидеть что-то, типа «l-wx—— 1 yukra yukra 64 апр. 1 03:43 1 -> /run/shm/test (deleted)»
3) Сказать «gdb -p PID» и потом «p close (1)» где «1» это имя ссылки из п. 2
Важно: Пока не наберёте detach, либо не выполните continue (c), процесс будет находиться в остановленном состоянии.
Важно2: отобрать файл, который например отдает апач — достаточно безболезненно (ну не считая того что клиент, качающий этот файл, обламается), а отобрать у мускуля файл, в который мускуль пишет — может закончиться печалькой.
lsof | grep deleted Гениально!! вчера два часа убил поиском кто съел свободное место, и только потом вспомнил про эту команду. Спасибо!
Да не за чт
А вы команды разделяете точкой с запятой?
Вот
/etc/init.d/mysql stop; /etc/init.d/mysql start
Это какой эффект даёт?
Кстати да, на VPS от DO столкнулся с тем, что битрих занял вообще все inode, умаялся убивать эти сотни тысяч файлов.
Ни одна команда с гугла и хабра не помогала, в итоге, после пары часов помогло:
find . -name ‘*’ -print0 | xargs -0 rm
Ну это известный способ. Xargs, кстати, будет работать очень медленно — лучше find с опциями -delete -print запускать.
> Это какой эффект даёт?
Чтобы команды выполнялись по очереди, независимо от результата выполнения предыдущей.
&& — выполнять следующую только при успешном выполнении предыдущей.
Просто все рецепты из интернета вываливались с ошибкой, а именно xargs сработал.
Про && знал, а про ; не в курсе. Похоже linux можно всю жизнь изучать )))
Есть ещё || — выполнять следующую команду, только если предыдущая вывались с ненулевым exit code
find . -name «*_sess» -print -delete будет нормально работать (и быстро на большом кол-ве файлов, быстрее только перлом, но там запомнить нереально).
После остановки/запуска апача и mysql сервер заработал, сайты стали доступны. Но что дальше? Команда lsof | grep deleted выводит то же самое. Где искать эти файлы? в /tmp/ их нет. И как предотвратить проблему? Из-за этого посыпалось несколько таблиц в базе, хотелось бы по-умному сделать. Все еще непонятно чем забит диск.
> 12
Сумбурненько.
Естественно, deleted-файлов в /tmp не будет — на то они и deleted.
Останови все демоны и смотри, что deleted-файлов после них не осталось. Если остались — смотри по пиду процесса, кто держит и разбирайся с тем, почему процесс не умер.
нашел причину, один из сайтов клиента писал в лог-файл. файл стал весить 41Гб, удалил, таблицы базы восстановил, хорошо что не критические данные хранились. а с deleted-файлами и процессами еще повожусь, спасибо за совет)
Не за что