С чего начать Первые шаги трек · 15 ступеней
Linux Labs

lsof — открытые файлы и порты процессов

5 мин Linux

lsof показывает, какой процесс держит файл, порт или удалённый, но ещё открытый файл.

Шпаргалка

5 команд Версия для печати
  • sudo lsof -i :5432 -nP кто на порту
  • sudo lsof +D /dir кто держит каталог (umount busy)
  • sudo lsof +L1 удалённые-но-открытые (место)
  • sudo lsof -p 1234 | wc -l сколько fd у процесса (утечка?)
  • sudo kill $(sudo lsof -t -i:8080) убить держащего порт

Обзор

«В Linux всё — файл»: обычные файлы, сокеты, каналы, устройства. lsof (LiSt Open Files) показывает, какие файлы/сокеты открыты и каким процессом. Часто нужен root.

bash
sudo lsof -i :80                  # кто слушает/держит порт 80
sudo lsof /var/log/app.log        # кто открыл этот файл
sudo lsof -u alice                # что открыл пользователь

Ключи

9
Ключ Значение
-i [:порт] сетевые сокеты (опц. по порту/хосту)
-nP без DNS- и port-резолва (быстро, числа)
-p PID файлы конкретного процесса
-c name процессы по имени команды
-u user по пользователю
+D /dir рекурсивно по каталогу (что держит ФС)
+L1 файлы с <1 ссылкой (удалённые-но-открытые)
-t только PID (для скриптов: kill $(lsof -t ...))
Ключ Что делает Пример
-i [:port] Только сетевые сокеты, опционально по порту или хосту. lsof -i :80
-n Не резолвить адреса в имена хостов (быстрее). lsof -i -n
-P Не резолвить номера портов в имена служб. lsof -i -P
-p PID Только файлы указанного процесса. lsof -p 1234
-c name Только процессы, чьё имя начинается с указанной строки. lsof -c nginx
-u user Только файлы, открытые указанным пользователем. lsof -u alice
+D dir Рекурсивно все файлы, открытые внутри каталога. lsof +D /mnt/data
+L1 Файлы с числом ссылок меньше 1 — удалённые, но ещё открытые. lsof +L1
-t Вывести только PID, без остальных колонок — удобно для подстановки в kill. kill $(lsof -t -i:8080)

Ничего не найдено. Попробуй запрос короче.

Рецепты

3

Частые задачи

bash
sudo lsof -i :5432                # процесс на порту (альтернатива ss)
sudo lsof -i -nP                  # все сетевые сокеты (без резолва)
sudo lsof -iTCP -sTCP:LISTEN -nP  # только слушающие TCP
sudo lsof +D /mnt/data            # кто держит каталог (umount)
sudo lsof +L1                     # удалённые, но открытые файлы
sudo lsof -p 1234                 # всё, что открыл процесс 1234
sudo lsof -c nginx                # всё, что открыли процессы nginx
sudo lsof -u alice -a -i          # alice И сеть (-a = AND)
sudo kill $(sudo lsof -t -i:8080) # убить того, кто на порту 8080

Столбец FD и блокировки

text
student@ubuntu:~$ lsof /tmp/lk
COMMAND  PID    USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
flock   1094 student    3rW  REG  253,4        0 2703 /tmp/lk
sleep   1096 student    3r   REG  253,4        0 2703 /tmp/lk
flock   1112 student    3r   REG  253,4        0 2703 /tmp/lk

FD — номер дескриптора, затем режим: r — чтение, w — запись, u — оба. Третья буква — блокировка файла: W — на запись всего файла, R — на чтение всего файла, w и r — на часть файла. Вместо номера бывают cwd (текущий каталог), txt (файл программы), mem (файл в памяти).

Здесь flock 1094 держит блокировку (3rW), sleep 1096 — его потомок с тем же открытым файлом, а flock 1112 открыл файл и ждёт: буквы блокировки у него нет. Ждущих видно и в /proc/locks (см. proc-filesystem).

Удалённые файлы: +L1 и DEL

Файл, который удалили или заменили новым, живёт, пока его держит процесс — это удалённый открытый файл. lsof +L1 показывает открытые файлы, у которых не осталось имени на диске. Так выглядит служба, чей бинарь заменили при обновлении:

text
student@ubuntu:~$ sudo lsof +L1
COMMAND    PID USER  FD   TYPE DEVICE SIZE/OFF NLINK NODE NAME
demo-slee 4214 root txt    REG  253,4    35336     0 4464
  /usr/local/bin/demo-sleep (deleted)

NLINK 0 — имён у файла нет, txt — это файл программы.

Удалённую общую библиотеку в памяти процесса +L1 не показывает: такой файл не открыт, а отображён в память. У lsof по процессу он отмечен DEL в столбце FD:

text
student@ubuntu:~$ sudo lsof -p 3830 | grep -E 'COMMAND|DEL'
COMMAND  PID USER   FD   TYPE  DEVICE SIZE/OFF  NODE NAME
sleep   3830 root  DEL    REG   253,4           2727
  /usr/local/lib/libdemo.so.1

Те же файлы с пометкой (deleted) — в /proc/<PID>/maps (см. proc-filesystem). Заменённый файл освобождается только с перезапуском процесса.

Неполадки

5

df показывает «полно», du — нет

Удалённый, но открытый процессом файл не освобождает место. Найди: sudo lsof +L1 → перезапусти держащий процесс (см. disk-usage).

umount: target is busy

Что-то держит ФС: sudo lsof +D /mnt/data (или fuser -vm /mnt/data). Закрой процессы (или cd из каталога) и отмонтируй (см. mount).

Порт занят, кто — непонятно

sudo lsof -i :PORT -nP или ss -tlnp.

Процесс «утёк» файловыми дескрипторами

sudo lsof -p PID | wc -l — сколько открыто; сравни с лимитом ulimit -n. Постоянный рост = утечка fd в приложении.

lsof долго думает

Резолвит DNS/порты/маунты — добавь -nP, при зависших NFS — может висеть на маунте.

Термины

1
удалённый открытый файл open unlinked file
Файл, последнее имя которого удалено, но процесс ещё держит его открытым, сохраняя доступ к данным. Ещё встречается в: unattended-upgrades: обновления безопасности без участия человека, /proc: процессы и ядро в виде файлов

См. также

  • ss — Кто слушает порты и какие соединения открыты — современная замена netstat.
  • disk-usage — Куда делось место и inode — df, du, поиск крупных файлов, ловушки.
  • processes — Просмотр, сигналы и приоритеты процессов; поиск пожирателей CPU/памяти.
Загрузка…