Относительно недавно упал один небольшой мощности сервер. Началось с того что я не смог по FTP закинуть необходимый файл, т.к. ОСь отказывалась его создавать ссылаясь на то, что No space left on device. Но при этом свободного места было более, чем достаточно. Как правило, такая ошибка возникает когда в системе слишком много небольших или вообще пустых файлов, которые не занимают всего имеющегося места, но исчерпывают запасы индексных дескрипторов, которые необходимы для работы каждого файла в Unix-системах. Обычно, в создании большого количества маленьких файлов виноват кривой скрипт и в моем случае так и было: один нехороший скрипт без задней мысли плодил пустые сессии без продыху. Но исправить его это еще пол дела, необходимо ликвидировать последствия его работы. Вот об этом я ниже поподробней и расскажу.
Для начала проверьте свободное место на диске, может и правда кончилось:
1
2
3
4
5
6
7
$ df
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/xvda1 5160576 2753864 2144568 57% /
tmpfs 125316 0 125316 0% /lib/init/rw
udev 111976 28 111948 1% /dev
tmpfs 125316 4 125312 1% /dev/shm
Как видите, места еще предостаточно и проблема точно не в этом. Тогда проверим количество индексных дескрипторов, может быть в них проблема:
1
2
3
4
5
6
7
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/xvda1 327680 327680 0 100% /
tmpfs 31329 4 31325 1% /lib/init/rw
udev 27994 389 27605 2% /dev
tmpfs 31329 3 31326 1% /dev/shm
Если у вас в столбике IUse% отобразилось 100% или около того, то очевидно, что именно недостаток индексных дескрипторов послужил причиной возникновения ошибки No space left on device.
Теперь нужно найти эти маленькие файлы и удалить, чтобы сервер возобновил свою работу в штатном режиме. Для их поиска можно воспользоваться следующей командой в терминале:
1
$ for i in /*; do echo $i; find $i |wc -l; done
Она будет рыскать по всем директориям начиная с корня и выводить количество файлов в каждой поддиректории по отношению к корню файловой системы. И как только вы увидите каталог с необычно большим количеством файлов (или выполнение команды вообще повиснет на долго), то повторите выполнение этой команды для этого подозрительного каталога, чтобы уточнить месторасположение огромного числа файлов, например, для /var:
1
$ for i in /var/*; do echo $i; find $i |wc -l; done
Как только вы максимально уточните место дислокации противника, можно приступить к их ликвидации во имя свободы индексных дескрипторов. Ликвидацию можно провести обычным рекурсивным удалением:
1
$ rm -rf /var/bad_directory/*
Где bad_directory та плохая директория, что содержит в себе этих мелких негодников.
Но внимание! Если есть опасность, что количество файлов может насчитывать сотни тысяч или даже миллионы, то не в коем случае не используйте rm для их удаления (и не смотрите директорию с помощью ls), т.к. это подвесит систему на очень долгое время (оооочень) или она упадёт. Лучше всего воспользоваться известным приёмом удаления через команду find. Тогда удаление будет проведено постепенно и вы даже сможете наблюдать за ходом процесса. Да, нагрузка на сервер будет всё равно большой, но при этом он не упадёт, немного ресурсов останется и для сайтов. Для этого используйте следующую команду:
1
$ find /var/bad_directory/. -type f -exec rm -v {} \;
После проведения массовых репрессий вы можете снова проверить количество свободных айнодов, которых должно значительно поприбавиться:
1
2
3
4
5
6
7
$ df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
/dev/xvda1 327680 91090 236590 28% /
tmpfs 31329 4 31325 1% /lib/init/rw
udev 27994 389 27605 2% /dev
tmpfs 31329 3 31326 1% /dev/shm
Вот и все, после этих нехитрых действий опасность будет ликвидирована, главное, не забудьте найти и пофиксить то, что вызвало столь массовое создание маленьких файлов иначе через некоторое время индексные дескрипторы снова закончатся и всё повторится. Удачи.