Кончилось место на сервере? А файлов меньше чем занятого места?

Опубликовано:

Нередко случается такое, что приложение говорит «cannot write blah to hdd, not enough space», хотя df -h говорит, что места ещё много.

Чаще всего такое поведение случается в трех случаях:

1) кончились inodes на диске
2) какой-то из демонов держит удаленные файлы.

Про inodes тоже понятно. Если у вас много-много мелких файлов, то inodes будут кончаться сильно быстрее, чем место на диске. Каждый файл будет кушать хотя бы одну inode. Если количество inodes меньше, чем блоков на диске — то они закончатся быстрее, чем свободное место (т.е. блоки).
Починить на лету это сложно (ну кроме как удалением той самой кучи мелких файлов). На типовом стеке LAMP-ы это случается чаще всего из-за файлов сессий (если вы их вынесли куда то из /var/lib/php5 и не настроили чистку нового каталога по крону) или из-за битриксов — небольшой сайт на битриксе с включенным кешированием скушает вам 300-400k inodes (а на digitalocean вам на виртуалке за 5 баксов дают 2kk inodes). Большой сайт на битриксе влегкую кушает 2-3kk inodes и не давится.

Проверить, сколько у вас inodes свободно можно командой df -i:

root@server:~# 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:

root@server:~# 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, удалили, но демоны всё ещё висят над этими файлами и пишут в них.
«Починить место» в данном случае можно так:

root@server:~# /etc/init.d/mysql stop; /etc/init.d/mysql start
root@server:~# /etc/init.d/syslog-ng stop; /etc/init.d/syslog-ng start

Само собой, если у вас там другие процессы в первом столбце — то перезапускать нужно их

Понравилась статья, расскажи о ней друзьям, нажми кнопку!