Про файл-призрак или как найти суслика, которого нет

Зайчатки разума

Записная книжка айтишника

Про файл-призрак или как найти суслика, которого нет

2019-12-24 14:21:35 — Evgeniy Shumilov

  Сегодня на работе столкнулся с интересным моментом. Ко мне подошёл разработчик и сказал, что на старом dev сервере закончилось место. Дело житейское, начал искать. Запустил ncdu (кстати, незаменимая утилита, всем рекомендую) и попытался найти, что же занимает место. Не нашёл, да и визуально показалось, что занято не так уж много. В нижней строке ncdu показывал Total disk usage равный 29ти гб при общем размере диска в 200 гб. При этом при попытке создать любой файл, система говорила об ошибке в связи с нехваткой места. 


  Вторым делом проверил айноды. df -i / показывал, что на корневом разделе занято 3% айнод, df -h / - что занято всё место под завязку. Потом меня посетила одна идея и я долго листал ман, пытаясь вспомнить необходимые ключи к lsof, в итоге нагуглил хороший список параметров к lsof, который тоже всем рекомендую. Нужным мне был параметр

sudo lsof +L1

  Он отображает открытые дескрипторы файлов, на которые меньше одной ссылки, т.е. некая именованная область хранения данных, у которой больше нет имени и на которую никто не ссылается. Другими словами, жил/был большой отладочный log файл, который писал nginx. Постепенно файл занял всё свободное место, после чего разработчик зашёл и удалил этот файл. После чего файл как суслик из ДМБ - его никто не видит, но он как бы есть. Запущенный процесс (в нашем случае nginx) не отпускает дескриптор файла и ОС не может считать место, занимаемое этим файлом свободным. 

Пример вывода sudo lsof +L1:

COMMAND     PID       USER   FD   TYPE DEVICE SIZE/OFF NLINK     NODE NAME
systemd-j   390       root  txt    REG    9,2   326224     0  6033164 /lib/systemd/systemd-journald (deleted)
systemd-l   571       root  txt    REG    9,2   618520     0  6033180 /lib/systemd/systemd-logind (deleted)
dbus-daem   572 messagebus  txt    REG    9,2   224208     0  1580294 /usr/bin/dbus-daemon (deleted)
php-fpm7.  1060   www-data    4u   REG    9,2        0     0  1310758 /tmp/.ZendSem.CF4mtM (deleted)
php-fpm7.  2446       root    4u   REG    9,2        0     0  1310758 /tmp/.ZendSem.CF4mtM (deleted)
php-fpm7.  2832   www-data    4u   REG    9,2        0     0  1310758 /tmp/.ZendSem.CF4mtM (deleted)
systemd    3894       root  txt    REG    9,2  1577232     0  6033178 /lib/systemd/systemd (deleted)
(sd-pam    3895       root  txt    REG    9,2  1577232     0  6033178 /lib/systemd/systemd (deleted)
bash      16531       root  txt    REG    9,2  1037528     0 13369404 /bin/bash (deleted)
php-fpm7. 18024   www-data    4ur  REG    9,2        0     0  1310758 /tmp/.ZendSem.CF4mtM (deleted)
bash      18729       root  txt    REG    9,2  1037528     0 13369404 /bin/bash (deleted)
bash      23796       root  txt    REG    9,2  1037528     0 13369404 /bin/bash (deleted)
php-fpm7. 29340   www-data    4u   REG    9,2        0     0  1310758 /tmp/.ZendSem.CF4mtM (deleted)

  Как можно видеть, в конце каждой строки есть "(deleted), кто как бы намекает, что файл был удалён. Нас интересует строка SIZE/OFF. Мы можем отсортировать значения по ней и вывести например, 10 самых жирных файлов, которые были удалены, но при этом всё ещё занимают место. Например, вот так:

$ sudo lsof +L1 | sed '1d' | sort -n -k 7 -r | head -n 5
postgres  29512   postgres   46u   REG    9,2 16777216     0  3544115 /var/lib/postgresql/9.5/main/pg_xlog/000000010000000F00000095 (deleted)
systemd    3894       root  txt    REG    9,2  1577232     0  6033178 /lib/systemd/systemd (deleted)
(sd-pam    3895       root  txt    REG    9,2  1577232     0  6033178 /lib/systemd/systemd (deleted)
bash      23796       root  txt    REG    9,2  1037528     0 13369404 /bin/bash (deleted)
bash      18729       root  txt    REG    9,2  1037528     0 13369404 /bin/bash (deleted)

  Заметьте, не смотря на то, что в числе удалённых числятся и /bin/bash и /lib/systemd/systemd, ещё не означает, что этих файлов физически нет на диске. Вполне возможно, что была открыта та же сессия /bin/bash, после чего сам интерпретатор успел обновиться, т.е. старая версия /bin/bash была удалена, а на её месте уже лежит новая. 
 

Теги: админское, linux

comments powered by Disqus