Про файл-призрак или как найти суслика, которого нет
Сегодня на работе столкнулся с интересным моментом. Ко мне подошёл разработчик и сказал, что на старом 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 была удалена, а на её месте уже лежит новая.