Удаление открытого файла в Linux | МАРС Телеком

ПерезвонимВам

Попробовать бесплатно
Нажимая ОТПРАВИТЬ я соглашаюсь с обработкой персональных данных
Вы также можете связаться с нашими специалистами по телефону 8 800 333-65-40 (звонок бесплатный по всей территории России).
аватарка
MARS Connector

Программа служит для подключения к услуге «Аренда виртуального сервера» и «Аренда 1С».

СКАЧАТЬ

Удаление открытого файла в Linux


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

Запросить демо
Листайте ниже

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

Такие вопросы очень любят задавать на собеседованиях бывалые админы, а в интернете про ответы на них не написал только ленивый. Тем не менее кандидаты все также из раза в раз продолжают делать круглые глаза. Максимум, что от них можно услышать — это «Иноды. Я слышал про иноды, но больше про них ничего не знаю».

В этой статье раз и навсегда внесём ясность в этом вопросе.

Удаление открытого файла в Linux

Чтобы проверить как работает файловая система в Linux, проведем небольшой эксперимент.

Подготовка

Для проведения всех тестов нам необходима виртуальная машина с практически любым дистрибутивом Linux и дополнительный диск. Благо в век виртуализации это сделать проще простого. Для наглядности возьмем диск в пару гигабайт и заранее подготовим его (базовые операции с дисками рассмотрим в другой статье).

Представим, что вы впервые вошли по ssh на сервер, у вас рутовые права и ваша задача просто разобраться с дисковой подсистемой.

Свободное место и свободные иноды

Первое, что мы сделаем, это проверим диски всем знакомой командой df (лишние данные убраны из вывода):

# df -h
Filesystem                          Size Used Avail Use% Mounted on
/dev/mapper/test_disk_01-lv_test_01 1.5G 4.5M  1.4G   1% /mnt/data

Утилита отображает занятое на файловой системе место в блоках 1К. Этой информации в большинстве случаев хватает лишь для констатации факта о % свободного места и не стоит на этом останавливать диагностику.

Проблемы с записью новых файлов может вызвать также нехватка инодов (inodes), поэтому полезно будет их проверить той же командой, но с другим ключом:

# df -i
Filesystem                           Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/test_disk_01-lv_test_01   98304    10   98294    1% /mnt/data

Используется 1% места на разделе. Запоминаем вывод команд, он нам понадобится для последующего анализа.

Создание файлов на диске

Далее создадим один большой файл на нашем диске. Сделать это проще всего утилитой dd, которая поставляется по умолчанию вместе с системой (предварительно создадим пару каталогов):

cd /mnt/data && mkdir {big,small}
dd if=/dev/zero of=big/file.img bs=1G count=1

И ещё создадим 10 маленьких файлов, но другим способом:

touch small/file{001..010}.img

Теперь снова смотрим два вывода df:

# df -h
Filesystem                          Size Used Avail Use% Mounted on
/dev/mapper/test_disk_01-lv_test_01 1.5G 1.1G  359M  75% /mnt/data

Как видно, теперь на диске занято 75%. А что с инодами?

# df -i
Filesystem                           Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/test_disk_01-lv_test_01   98304    23   98281    1% /mnt/data

Количество инод изменилось на 13, хотя файлов мы создали всего 11.

Эксперимент с удалением открытого файла

Теперь посмотрим на ситуацию другой утилитой, которую также обязательно нужно использовать для диагностики. Речь о du:

# du -shc ./*
1.1G ./big
4.0K ./small
1.1G total

Примерно занят 1ГБ.

Примечание: для изучения ключей наберите в консоли man du. Актуально также и для других утилит, рассматриваемых в статье.

Теперь сымитируем что-то похожее на блокировку файла (если будут предупреждения, соглашайтесь):

# less +F big/file.img >/dev/null &
[2] 16483

Команда просто открывает файл на чтение и отправляет задание в бэкграунд. Теперь удаляем файл:

rm -f big/file.img

После этого проверяем свободно место:

# df -h
Filesystem                          Size Used Avail Use% Mounted on
/dev/mapper/test_disk_01-lv_test_01 1.5G 1.1G  359M  75% /mnt/data

И свободные иноды:

# df -i
Filesystem                           Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/test_disk_01-lv_test_01   98304    23   98281    1% /mnt/data

В итоге место не освободилось, хотя файл, казалось бы, удален. Инодов используется столько же. Но может быть du покажет нам что-то другое:

# du -shc ./*
4.0K ./big
4.0K ./small
8.0K total

Занято 8Кб. Ок, есть ещё одна утилита, которая лучше других объяснит что происходит, это lsof:

# lsof | grep deleted
COMMAND   PID TID USER FD TYPE DEVICE   SIZE/OFF NODE NAME
less    16483     root 3r  REG  253,2 1073741824   11 /mnt/data/big/file.img (deleted)

Мы посмотрели все, что хотели, можно заканчивать.

Завершение эксперимента

Сворачиваем наш эксперимент — убиваем процесс, который мы ранее запустили в фоновом режиме:

kill -9 16483

Теперь снова проверяем свободное место:

# df -h
Filesystem                          Size  Used Avail Use% Mounted on
/dev/mapper/test_disk_01-lv_test_01 1.5G  4.5M  1.4G   1% /mnt/data

А также иноды:

# df -i
Filesystem                           Inodes IUsed   IFree IUse% Mounted on
/dev/mapper/test_disk_01-lv_test_01   98304    22   98282    1% /mnt/data

Большой файл удалился, место и иноды освободились. Смысла проверять вывод du нет, она покажет то же самое, что и в предыдущий раз.

Выводы

Что все же произошло? А произошло следующее: информация от du и df до удаления большого файла была очевидной и объяснений не требует. За исключением одного момента — почему файлов создали 11, а количество инодов увеличилось на 13? Тут все просто. Наверно все слышали выражение, что все в линуксе — файл 1? И каталог тоже, а их мы создали два.

Далее мы удалили файл, который открыт на чтение другим процессом. Команда rm удалила ссылку на файл, которую хранит объект каталога, но не смогла удалить файл физически с диска, поскольку файл был открыт на чтение другой программой.

Примечание: догадываетесь почему нельзя чистить логи путем простого удаления файлов без перезапуска приложения?

Хоть файл уже и не имел имени, но все ещё имел файловый дескриптор (= инод), к которому продолжала обращаться программа. Это было также хорошо заметно по выводу lsof — файл был помечен как удаленный. Как только программу остановили, файл освободился и система смогла завершить начатое — удалить файл и зависимые структуры данных на диске окончательно.

В показаниях утилиты du также нет ничего странного, ведь она считывает все перечисленные имена файлов в каталоге и оценивает их размер. Поскольку ссылку на имя большого файла удалили, du не смогла оценить его объем, зато это смогла сделать df, ведь она оценивает реальный занятый объем на диске в блоках без привязки к именам. Вот весь секрет.


https://marstel.ru/rent1c

Уже уходите?Хотите, перезвоним Вам за 30 секунд?

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

Пользовательское соглашение Звонок для Вас бесплатный