Введение / Зачем это нужно
lsof (List Open Files) — это мощная утилита командной строки в Linux, которая позволяет увидеть, какие процессы в системе имеют открытыми файлы, каталоги, сетевые сокеты, устройства и т.д. В Unix-подобных системах почти всё является файлом, поэтому эта команда — основной инструмент диагностики для системных администраторов, разработчиков и DevOps-инженеров.
Вы научитесь решать частые проблемы:
- «Порт 8080 уже занят, но каким процессом?»
- «Не могу удалить файл /tmp/app.log, говорится, что он используется. Кто его держит?»
- «Какие сетевые соединения активны у моего приложения?»
- «Почему процесс потребляет так много дескрипторов?»
Это руководство содержит конкретные, проверенные команды с объяснениями, которые вы сможете использовать сразу.
Требования / Подготовка
- Доступ к терминалу Linux (Ubuntu, CentOS, Debian, RHEL, Fedora и др.).
- Права суперпользователя (sudo). Многие команды, особенно связанные с сетевыми портами и процессами других пользователей, требуют прав администратора для корректного отображения информации.
- Установленный пакет
lsof. В большинстве дистрибутивов он есть по умолчанию, но в минимальных установках может отсутствовать.- Debian/Ubuntu:
sudo apt update && sudo apt install lsof - RHEL/CentOS/Fedora:
sudo yum install lsofилиsudo dnf install lsof
- Debian/Ubuntu:
- Базовое понимание командной строки и концепции PID (идентификатор процесса).
Пошаговая инструкция
Шаг 1: Базовый синтаксис и просмотр всех открытых файлов
Запуск lsof без аргументов выведет список всех открытых файлов текущего пользователя.
lsof
Пример вывода (упрощённо):
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1234 user cwd DIR 8,1 4096 2 /
bash 1234 user txt REG 8,1 1028096 12345 /bin/bash
bash 1234 user mem REG 8,1 1985224 67890 /lib/x86_64-linux-gnu/libc-2.31.so
...
Ключевые столбцы:
COMMAND— имя исполняемого файла процесса.PID— идентификатор процесса.USER— владелец процесса.FD— файловый дескриптор (cwd — текущий каталог, txt — исполняемый код, mem — отображённая в память область).TYPE— тип файла (REG — обычный файл, DIR — каталог, CHR — символьное устройство, IPv4/IPv6 — сетевой сокет).NAME— путь к файлу или информация о сокете.
Для полной системной картины (всех пользователей) используйте sudo:
sudo lsof
Шаг 2: Поиск процессов, открывших конкретный файл или каталог
Это самая частая задача: «Кто использует этот файл?».
Для одного файла:
lsof /path/to/file.log
Пример: lsof /var/log/syslog
Рекурсивный поиск по каталогу (все файлы внутри):
lsof +D /home/user/documents/
⚠️ Важно: Опция +D может работать очень медленно на больших каталогах, так как проверяет каждый подкаталог. Для быстрой проверки конкретного файла используйте первый вариант.
Шаг 3: Поиск процесса по его PID (что открыл процесс)
Если вы знаете PID процесса (например, 5678), посмотрите, какие ресурсы он использует:
lsof -p 5678
Можно указать несколько PID через запятую: lsof -p 5678,9012.
Это полезно для анализа работы запущенного демона, контейнера или подозрительного процесса.
Шаг 4: Поиск процесса, слушающего сетевой порт
Классическая задача: «Порт 3000 занят, какой процесс его слушает?».
sudo lsof -i :3000
Пример вывода:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
node 4321 user 20u IPv6 123456 0t0 TCP *:3000 (LISTEN)
Здесь видно, что порт 3000 слушает процесс node (Node.js) с PID 4321.
Поиск по имени службы/порта (если порт известен, например, 80 для HTTP):
sudo lsof -i :http
# или
sudo lsof -i :80
Шаг 5: Расширенная фильтрация сетевых соединений
Комбинация опций -i позволяет тонко настраивать фильтрацию.
Только TCP-соединения:
sudo lsof -i tcp
Только UDP-сокеты:
sudo lsof -i udp
Соединения в состоянии LISTEN (слушающие порты):
sudo lsof -i -s tcp:listen
Опция -s позволяет фильтровать по состоянию соединения (established, listen, close_wait и др.).
Соединения с конкретного или на конкретный IP-адрес:
# Все соединения с удалённого адреса 192.168.1.100
sudo lsof -i @192.168.1.100
# Все соединения на локальный интерфейс 192.168.1.5:80
sudo lsof -i @192.168.1.5:80
Шаг 6: Поиск файлов, открытых определённым пользователем
Чтобы увидеть все файлы, открытые пользователем apache или www-data:
sudo lsof -u apache
Можно указать нескольких пользователей: lsof -u user1,user2.
Шаг 7: Комбинирование фильтров (логическое И)
Фильтры в lsof по умолчанию объединяются через И (логическое умножение). Это очень мощно.
Пример: Найти все TCP-соединения (-i tcp), которые слушают (-s tcp:listen) и принадлежат процессу с именем nginx (-c nginx).
sudo lsof -i tcp -s tcp:listen -c nginx
Где:
-c <command>— фильтр по первым символам имени команды (можно использовать^nginxдля точного совпадения с начала строки).
Ещё пример: Какие файлы открывает пользователь postgres в каталоге /var/lib/postgresql?
sudo lsof -u postgres +D /var/lib/postgresql
Шаг 8: Полезные опции для удобного вывода
-n— не преобразовывать IP-адреса в имена хостов (ускоряет вывод).-P— не преобразовывать номера портов в имена служб (порт 80 вместо http).-F— вывод в формате, удобном для парсинга скриптами (каждая строка — поле, начинается с символа-идентификатора).-t— вывод только PID (удобно для передачи в другие команды, например,kill).
Пример быстрой и чистой проверки слушающих портов:
sudo lsof -i -s tcp:listen -n -P
Шаг 9: Практический пример — остановка процесса, блокирующего порт
Допустим, вы запускаете веб-сервер на порту 8080 и получаете ошибку Address already in use.
- Найдите виновника:
sudo lsof -i :8080
В выводе смотритеPID(например, 12345) иCOMMAND(например,java). - Остановите процесс (если это не критичная служба):
sudo kill 12345
Если процесс не реагирует наSIGTERM(обычныйkill), используйте принудительное завершение:sudo kill -9 12345 - Перезапустите ваш сервер. Порт теперь должен быть свободен.
Шаг 10: Поиск утечек файловых дескрипторов
Если процесс (особенно долгоживущий) открывает много файлов и не закрывает их, это может привести к исчерпанию лимита системы ( Too many open files).
- Посмотреть, сколько дескрипторов открыто у процесса:
lsof -p <PID> | wc -l
(Строка сCOMMANDтоже учитывается, но для оценки порядок величин подходит). - Посмотреть топ-процессов по количеству открытых файлов:
sudo lsof | awk '{print $2}' | sort | uniq -c | sort -nr | head -20
Эта команда:awk '{print $2}'— вырезает второй столбец (PID).sort | uniq -c— подсчитывает количество вхождений каждого PID.sort -nr— сортирует по убыванию количества.head -20— показывает топ-20.
Проверка результата
После выполнения любой команды lsof проверьте, что вывод содержит ожидаемые данные:
- Для поиска по файлу: В столбце
NAMEдолжен быть указан ваш путь. - Для поиска по порту: В столбце
NAMEдолжно быть*:портилиIP:порт, а вTYPE—IPv4илиIPv6. - Для поиска по PID: В списке должен присутствовать указанный PID.
Если вывод пуст, это означает, что соответствующие ресурсы не открыты (файл не используется, порт не слушается) или вы запустили команду без sudo и не видите процессы других пользователей.
Возможные проблемы
Проблема 1: lsof: command not found
Причина: Пакет не установлен. Решение: Установите через менеджер пакетов вашего дистрибутива (см. Требования).
Проблема 2: Пустой вывод при поиске по порту (sudo lsof -i :80 ничего не показывает)
Причина 1: Никакой процесс действительно не слушает этот порт. Порт свободен.
Причина 2: Вы ищете порт IPv6, а процесс слушает IPv4 (или наоборот). Попробуйте sudo lsof -i -P -n | grep :80 для общего поиска.
Причина 3: Порт находится в состоянии TIME_WAIT (закрытое соединение, которое ещё не освободилось полностью). lsof по умолчанию не показывает такие сокеты. Используйте netstat -an | grep :80 или ss -ltnp для более полной картины.
Проблема 3: permission denied или недостаточно прав
Причина: Вы пытаетесь увидеть открытые файлы процесса, принадлежащего другому пользователю (особенно root), без sudo.
Решение: Всегда используйте sudo для системного обзора: sudo lsof.
Проблема 4: Команда lsof работает очень медленно
Причина: Использование опции +D на большом каталоге или фильтрация по сложному шаблону.
Решение:
- Избегайте
+Dна корневых каталогах (/,/home). Ищите конкретные файлы. - Используйте более точные фильтры (
-p,-u,-c) для уменьшения объема обрабатываемых данных. - Добавьте
-nи-Pдля отключения преобразования имён (ускоряет работу).
Проблема 5: Не могу удалить файл, хотя lsof не показывает его использование
Причина 1: Файл удалён, но ещё открыт процессом. В lsof такой файл отобразится как (deleted) в конце строки NAME. Процесс продолжает писать в этот уже удалённый файловый дескриптор, занимая место на диске.
Решение: Остановите процесс (kill), который держит дескриптор. Освобождение места на диске произойдёт автоматически после завершения процесса.
Причина 2: Файл используется не процессом, а ядром (например, как swap-файл или корень смонтированной файловой системы). lsof может не показать такие системные использования. Используйте fuser -v /path/to/file или lsof /path/to/file | grep -v '(deleted)' для чистоты вывода.