В Linux многие объекты считаются файлами, независимо от того, является ли объект на самом деле файлом, устройством, каталогом или сокетом. Перечислить файл легко, для этого есть встроенная оболочка ls
. Но что, если пользователь хочет увидеть, какие файлы в данный момент открываются процессом веб-сервера? Или если этот пользователь хочет узнать, какие файлы открываются в определенном каталоге? Вот где lsof
вступает в игру. Представьте себе, lsof
как ls
с добавлением «открытых файлов».
Обратите внимание, что, хотя в BSD есть другая утилита для этой работы, есть fstat
и другие варианты Unix (например, Solaris) lsof
. Опции и флаги отличаются на других платформах, также как и внешний вид вывода, но, как правило, знания в этой статье должны быть применимы и для них.
Во-первых, давайте посмотрим на формат lsof
вывода и как его читать. Обычный вывод lsof
без каких-либо параметров будет выглядеть следующим образом. Это было обрезано для удобства чтения.
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
init 1 root cwd DIR 254,1 4096 2 /
init 1 root rtd DIR 254,1 4096 2 /
init 1 root txt REG 254,1 36992 7077928 /sbin/init
init 1 root mem REG 254,1 14768 7340043 /lib/x86_64-linux-gnu/libdl-2.13.so
init 1 root mem REG 254,1 1603600 7340040 /lib/x86_64-linux-gnu/libc-2.13.so
init 1 root mem REG 254,1 126232 7340078 /lib/x86_64-linux-gnu/libselinux.so.1
init 1 root mem REG 254,1 261184 7340083 /lib/x86_64-linux-gnu/libsepol.so.1
init 1 root mem REG 254,1 136936 7340037 /lib/x86_64-linux-gnu/ld-2.13.so
init 1 root 10u FIFO 0,14 0t0 4781 /run/initctl
Эти столбцы означают следующее:
- КОМАНДА - процесс, которому принадлежит открытый файл, в этом примере все связано с
init
.
- PID - идентификационный номер процесса.
- USER - пользователь, под которым запускается процесс. Ведь
init
это почти всегда root
.
- FD - дескриптор файла, наиболее распространенным из которых является:
cwd
- Текущий рабочий каталог (вы можете заметить сходство с pwd
командой, которая печатает текущий рабочий каталог).
rtd
- Корневой каталог процесса.
txt
- A text file
, это может означать либо файл конфигурации, относящийся к процессу, либо «исходный код», относящийся к процессу или принадлежащий ему.
mem
- так называемый «файл отображения памяти», который означает сегмент виртуальной памяти (читай: RAM), который был назначен файлу.
- Число - число представляет фактический дескриптор файла, символ после числа - режим, в котором файл открывается:
r
- Читать.
w
- Напишите.
u
- Прочитайте и напишите.
- TYPE - указывает фактический тип файла, наиболее распространенными являются:
REG
- Обычный файл.
DIR
- Каталог.
FIFO
- Первым пришел-первым вышел.
- DEVICE - основной и младший номер устройства, на котором хранится файл.
- РАЗМЕР - Размер файла в байтах.
- NODE - номер инода файла.
- ИМЯ - имя файла.
Это может быть немного подавляющим на данный момент, но если вы работаете с lsof
несколько раз, это быстро впитается в ваш мозг.
Как уже упоминалось выше, вывод lsof
здесь был сокращен. Без каких-либо аргументов или фильтров, lsof
производит сотни строк вывода, которые только оставят вас в замешательстве.
Есть два основных подхода к решению этой проблемы:
- Используйте один или несколько параметров
lsof
командной строки, чтобы сузить результаты.
- Передайте результат через, например
grep
,.
Хотя последний вариант может показаться более удобным, поскольку вам не нужно запоминать параметры lsof
командной строки, он, как правило, не такой гибкий и эффективный, поэтому мы остановимся на первом.
Давайте представим, что вы хотите открыть файл в своем любимом текстовом редакторе и что текстовый редактор сообщает, что его можно открыть только в режиме только для чтения, поскольку другая программа уже обращается к нему. lsof
поможет вам узнать, кто является преступником:
lsof /path/to/your/file
Это произведет вывод, подобный этому:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
vim 2679 root 5w REG 254,1 121525 6035622 /root/lsof.txt
Видимо, вы забыли закрыть и старую сессию! Очень похожая проблема возникает, когда вы пытаетесь размонтировать NFS-ресурс и umount
говорит, что не может, потому что что-то все еще обращается к смонтированной папке. Опять же, lsof
может помочь вам с выявлением виновника:
lsof +D /path/to/your/directory/
Обратите внимание на косую черту, это важно. В противном случае lsof
предположим, что вы имеете в виду обычный файл. Не смущайтесь +
перед флажком - в lsof
нем так много опций командной строки, которые нужны +
в дополнение к более распространенным -
. Вывод будет выглядеть так:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mocp 5637 music 4r REG 0,19 10147719 102367344 /home/Music/RMS_GNU_SONG.ogg
Это означает, что процесс mocp
с идентификатором PID 5637
, принадлежащим пользователю music
, открыл файл с именем RMS_GNU_SONG.ogg
. Однако даже после закрытия этого процесса все еще остается проблема - том NFS не может быть размонтирован.
lsof
имеет -c
флаг, который отображает файлы, открытые произвольным именем процесса.
lsof -c mocp
Это приведет к выводу, похожему на это:
mocp 9383 music 4r REG 0,19 10147719 102367344 /home/Music/ANOTHER_RMS_GNU_SONG.ogg
В этом примере есть еще один экземпляр mocp
запуска, не позволяющий отключить общий ресурс. После завершения этого процесса вы хотите убедиться, что у пользователя music
нет других потенциально проблемных файлов. lsof
имеет -u
флаг для отображения файлов, открытых конкретным пользователем. Помните, что файл не всегда является обычным файлом на вашем жестком диске!
lsof -u music
Вы также можете передать несколько пользователей, ��азделенных запятыми:
lsof -u music,moremusic
Важное замечание по поведению по умолчанию lsof
: результаты ИЛИ основе, что означает , что вы будете видеть результаты файлов , открытых процессами, которые принадлежат либо пользователю music
, либо пользователю moremusic
. Если вы хотите увидеть процессы сопоставления результатов, принадлежащие обоим пользователям, вам нужно будет передать флаг -a
:
lsof -au music, moremusic
Поскольку оба пользователя находятся в группе musicusers
, вы также можете перечислить файлы на основе группы:
lsof -g musicusers
Вы также можете комбинировать флаги командной строки:
lsof -u music,moremusic -c mocp
or
lsof -u ^music +D /home/Music
В последней строке мы добавили еще один специальный флаг - ^
, который обозначает логическое НЕ . Если после выполнения этой команды выходные данные будут пустыми, размонтирование, скорее всего, будет успешным.
В предыдущих примерах мы в основном смотрели на обычные файлы. Как насчет сокетов и сетевых подключений?
Для просмотра списка всех текущих сетевых подключений lsof
есть -i
флаг:
lsof -i
Вывод выглядит аналогично тому, что мы видели до сих пор ...
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
owncloud 3509 myuser 25u IPv4 44946 0t0 TCP strix.local:34217->myserver.vultr.com:https (ESTABLISHED)
firefox 3612 myuser 82u IPv4 49663 0t0 TCP strix.local:43897->we-in-f100.1e100.net:https (ESTABLISHED)
ssh 3784 myuser 3u IPv4 10437 0t0 TCP strix.local:51416->someserver.in:ssh (ESTABLISHED)
wget 4140 myuser 3w IPv4 45586 0t0 TCP strix.local:54460->media.ccc.de:http (CLOSE_WAIT)
... за исключением одного различия: вместо имен файлов или каталогов в столбце NAME
теперь отображается информация о соединении. Каждое соединение состоит из следующих частей:
- Протокол.
- Локальное имя хоста.
- Исходный порт соединения.
- DNS-имя получателя.
- Порт назначения.
- Состояние связи.
Как и во многих других инструментах, вы можете отказаться от разрешения имен DNS и портов ( -n
и -P
, соответственно). Флаг -i
принимает дополнительные параметры. Вы можете указать, показывать или нет tcp
, udp
либо icmp
подключения, либо определенные порты:
lsof -i :25
or
lsof -i :smtp
Опять же, параметры могут быть объединены. Следующий пример ...
lsof -i tcp:80
... покажет вам только TCP-соединения через порт 80. Вы также можете комбинировать его с опциями, которые вы уже знаете из «классических» файлов:
lsof -a -u httpd -i tcp
Это покажет вам все TCP-соединения, открытые пользователем httpd
. Обратите внимание на -a
флаг, который изменяет поведение по умолчанию lsof
(как упоминалось ранее). Как и в большинстве инструментов командной строки, вы можете пойти очень глубоко. Следующее покажет только TCP-соединения, состояние которых «ESTABLISHED»:
lsof -i -s TCP:ESTABLISHED
На этом этапе вы должны иметь lsof
общее представление о том , как работает, а также некоторые распространенные случаи использования. Для получения дополнительной информации см. Справочную lsof
страницу вашей системы.