Полное руководство по lsof в Linux — практические советы от устранения конфликтов портов до освобождения места от удаленных файлов

Обзор

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

Базовая проверка lsof и просмотр открытых файлов определенного пользователя или процесса

Чтобы проверить, установлена ли в системе команда lsof, и установить пакет в случае его отсутствия, выполните команду command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof).

command -v lsof >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y lsof)

Чтобы проверить установленную версию и сведения о сборке команды lsof, выполните команду lsof -v.
⚙️ [Основные опции]

-u : выводит список файлов и процессов, открытых определенной учетной записью пользователя.
-c : фильтрует список файлов, открытых процессами, имя которых начинается с указанного.
-p : проверяет список файлов, открытых определенным идентификатором процесса (PID).
-i : находит процессы, использующие сетевые сокеты и определенные порты.
+D : рекурсивно ищет список открытых файлов в указанном каталоге и его подкаталогах.
-t : компактно выводит только идентификаторы процессов (PID) по одному на строку, что удобно для использования в скриптах.

lsof -v

Чтобы подготовить тестовый каталог и файл для практической работы с lsof, выполните команду mkdir -p /tmp/lsof_lab && echo '테스트 파일 내용' > /tmp/lsof_lab/sample.txt.

mkdir -p /tmp/lsof_lab && echo ‘테스트 파일 내용’ > /tmp/lsof_lab/sample.txt

Чтобы процесс удерживал созданный тестовый файл открытым, запустите отслеживание в фоновом режиме с помощью команды tail -f /tmp/lsof_lab/sample.txt &.

tail -f /tmp/lsof_lab/sample.txt &

Команда lsof -u $(whoami) | head -n 15 выводит первые 15 строк списка файлов, занятых процессами текущего вошедшего в систему пользователя.
Здесь можно увидеть подробную информацию о файлах, открытых текущей учетной записью, включая базовые системные библиотеки и исполняемые файлы.

lsof -u $(whoami) | head -n 15

Команда lsof -c tail находит и отображает список файлов и библиотек, открытых процессом с именем tail.
С ее помощью можно проверить, на какие файловые дескрипторы и разделяемые библиотеки ссылается команда tail, запущенная в фоновом режиме.

lsof -c tail

После завершения практики выполните команду killall tail 2>/dev/null || true, чтобы безопасно завершить работающий в фоновом режиме процесс tail и освободить ресурсы.

killall tail 2>/dev/null || true

Проверка сетевых портов и устранение конфликтов процессов

Для подготовки среды тестирования портов и разрешения конфликтов процессов проверьте, установлен ли в системе python3, и при необходимости установите пакет.

command -v python3 >/dev/null 2>&1 || (apt-get update -qq && apt-get install -y python3)

Для проверки занятости сетевого порта запустите простой веб-сервер на порту 8080 в фоновом режиме.

python3 -m http.server 8080 >/dev/null 2>&1 &

Подождите 1 секунду, пока запущенный в фоновом режиме веб-сервер корректно привяжется к порту 8080.

sleep 1

Команда lsof -i :8080 отображает процесс, использующий порт 8080.
В выводе команды видно, что процесс python3 с PID 371 ожидает подключений на порту 8080 в состоянии LISTEN.

lsof -i :8080

Команда lsof -i -P -n | head -n 15 быстро выводит список сетевых сокетов системы в числовом виде без преобразования номеров портов и IP-адресов.
Поскольку эта команда пропускает обратное разрешение DNS и сопоставление имен сервисов портов, она позволяет мгновенно оценить занятость портов без задержек.

lsof -i -P -n | head -n 15

Команда lsof -i TCP:8080 -sTCP:LISTEN точно фильтрует и выводит только соединения по протоколу TCP на порту 8080, находящиеся в состоянии LISTEN.
Это полезно для исключения лишних активных сессий и точного определения процесса-демона, который действительно ожидает входящих подключений на этом порту.

lsof -i TCP:8080 -sTCP:LISTEN

После завершения практики принудительно завершите процесс фонового веб-сервера, занимавшего TCP-порт 8080, и освободите ресурсы.

fuser -k 8080/tcp 2>/dev/null || kill $(lsof -t -i :8080) 2>/dev/null || true

Отслеживание файлов, блокирующих каталоги и размонтирование (Device Busy)

Чтобы воспроизвести ситуацию блокировки каталога и невозможности размонтирования, создайте тестовый каталог и перейдите в него.

mkdir -p /tmp/mount_test && cd /tmp/mount_test

Чтобы создать файл лога, к которому будет обращаться процесс, выполните команду echo '작업 중인 파일' > active_work.log.

echo ‘작업 중인 파일’ > active_work.log

Запустите процесс sleep в фоновом режиме, перенаправив созданный файл на стандартный ввод, чтобы удерживать его занятым.

sleep 30 < active_work.log &

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

cd /root || cd ~

Команда lsof +D /tmp/mount_test рекурсивно отслеживает и выводит все открытые файлы и процессы в указанном каталоге и его подкаталогах.
По результатам вывода можно убедиться, что процесс sleep с PID 450 ссылается на этот каталог как на свой текущий рабочий каталог (cwd) и открыл файл active_work.log в режиме чтения (0r), препятствуя тем самым размонтированию.

lsof +D /tmp/mount_test

После завершения практики корректно завершите процесс sleep, работавший в фоновом режиме и блокировавший каталог и файл.

killall sleep 2>/dev/null || true

Удалите временный тестовый каталог и все содержащиеся в нем файлы, чтобы очистить ресурсы системы.

rm -rf /tmp/mount_test

Восстановление и очистка файлов-призраков (deleted), которые удалены, но занимают место на диске

Чтобы протестировать утечку дискового пространства, создайте тестовый каталог и сгенерируйте в нем тестовый файл размером 10 МБ.

mkdir -p /tmp/leak_test && dd if=/dev/zero of=/tmp/leak_test/large.img bs=1M count=10 >/dev/null 2>&1

Запустите отслеживание в фоновом режиме, чтобы процесс продолжал удерживать дескриптор созданного файла большого размера.

tail -f /tmp/leak_test/large.img &

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

rm -f /tmp/leak_test/large.img

Команда lsof | grep '(deleted)' | head -n 5' выводит список файлов, которые удалены из файловой системы, но все еще удерживаются процессами и занимают дисковое пространство.
С ее помощью можно быстро обнаружить файлы-призраки и соответствующие им процессы, из-за которых дисковое пространство не освобождается даже после выполнения команды rm.

lsof | grep ‘(deleted)’ | head -n 5

На основе идентификатора процесса, полученного с помощью lsof -t, выведите список файловых дескрипторов в каталоге /proc/$TARGET_PID/fd/.
Проверив номер файлового дескриптора, на который ссылается процесс, можно освободить место без перезапуска процесса или при необходимости восстановить исходные удаленные данные через этот дескриптор.

TARGET_PID=$(lsof -t /tmp/leak_test/large.img 2>/dev/null | head -n 1) && [ -n “$TARGET_PID” ] && ls -l /proc/$TARGET_PID/fd/ || true

После завершения практики безопасно завершите фоновый процесс, который продолжал удерживать файл-призрак, чтобы полностью освободить дисковое пространство.

killall tail 2>/dev/null || true

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

rm -rf /tmp/leak_test

Мы рассмотрели основные практические советы по использованию команды lsof: от устранения конфликтов портов до освобождения дискового пространства от удаленных файлов.
Надеемся, что этот материал поможет вам эффективно решать задачи администрирования серверов и диагностики неполадок на практике.