zaLinux.ru

Как пользоваться lsof для просмотра открытых файлов (в Linux всё является файлами)


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

В Linux всё является файлами

Часто цитируемая фраза о том, что всё в Linux является файлом, является своего рода правдой. Файл представляет собой набор байтов. Программы и устройства (принтер, экран, клавиатура, мышь, терминал, сетевая карта) могут генерировать или принимать потоки байт, и в этом качестве они сами проявляются как файлы. Многие системные компоненты, такие как клавиатуры, сокеты, принтеры и коммуникационные процессы, принимают или генерируют потоки байтов. Поскольку они принимают, генерируют или принимают и генерируют потоки байтов, эти устройства могут обрабатываться — на очень низком уровне — как файлы. Кроме обычных файлов, файлами также являются директории (папки), сетевые сокеты (подключения по сети), устройства (диски, терминалы, клавиатура, мышь и прочее — это всё файлы), pipe (технология обмена данными между процессами).

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

Файлы данных и программ, которые находятся на вашем жёстком диске, являются обычными файлами файловой системы. Мы можем использовать команду ls, чтобы вывести их и узнать некоторые детали о них. Но как мы узнаем обо всех других процессах и устройствах, которые рассматриваются как файлы? Для этого используется команда lsof. Она выводит списки открытых файлов в системе. То есть она перечисляет всё, что обрабатывается, как если бы это был файл.

Команда lsof

lsof означает ‘LiSt Open Files’ (список открытых файлов). Эта программа используется чтобы узнать, какие файлы открыты и каким процессом.

Для чего нужно знать, какие файлы открыты? Эта информация поможет узнать о многом происходящем в системе, об устройстве и работе Linux, а также решить проблемы, например, когда вы не можете размонтировать диск из-за того, что устройство используется, но вы не можете найти, какой именно программой.

Многие процессы или устройства, о которых lsof может сообщать, принадлежат root или были запущены пользователем root, поэтому вам нужно будет использовать команду sudo с lsof.

И поскольку этот список будет очень длинным, то можно передать его команде less:

sudo lsof | less

До появления вывода lsof, пользователи могут увидеть предупреждающее сообщение в окне терминала.

lsof: WARNING: can't stat() fuse.gvfsd-fuse file system /run/user/1000/gvfs
      Output information may be incomplete.

lsof пытается обработать все смонтированные файловые системы. Это предупреждающее сообщение появляется из-за того, что lsof обнаружил виртуальную файловую систему GNOME (GVFS). Это особый случай файловой системы в пространстве пользователя (FUSE). Он действует как мост между GNOME, его API и ядром. Никто, даже root, не может получить доступ к одной из этих файловых систем, кроме владельца, который её смонтировал (в данном случае, текущий пользователь). Вы можете игнорировать это предупреждение. Если же вы хотите получить доступ к данной файловой системе, то запустите lsof без sudo.

Шапка вывода lsof:

Значение столбцов lsof

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

  • COMMAND: Имя команды, связанной с процессом, который открыл файл.
  • PID: Идентификационный номер процесса, который открыл файл.
  • TID: Идентификационный номер задачи (потока) . Пустой столбец означает, что это не задача; это процесс.
  • TASKCMD: это имя команды задачи. Обычно это будет то же самое, что и процесс, названный в столбце COMMAND, но некоторые реализации задач (например, Linux) позволяют задаче изменить имя своей команды.
  • USER: это идентификационный номер пользователя или логин пользователя, которому принадлежит процесс, обычно то же самое, что сообщает ps. Однако в Linux USER — это идентификационный номер пользователя или логин, который владеет каталогом в /proc, где lsof находит информацию о процессе. Обычно это то же самое значение, которое сообщает ps, но может отличаться, если процесс изменил свой эффективный идентификатор пользователя (также смотрите Что такое файловая система /proc в Linux)
  • FD: показывает файловый дескриптор файла. Файловые дескрипторы описаны ниже.
  • TYPE: тип узла, связанного с файлом. Виды данных типов описаны ниже.
  • DEVICE: содержит номера устройств, разделённые запятыми, для специальных символьных, специальных блочных, обычных файлов, каталогов или NFS. Также может отображаться базовый адрес или имя устройства с сокетом Linux AX.25.
  • SIZE/OFF: Показывает размер файла или смещение файла в байтах.
  • NODE: Показывает номер узла локального файла или номер узла NFS-файла на хосте сервера или тип интернет-протокола. Может отображаться STR для потока, IRQ или номер инода устройства с сокетом Linux AX.25.
  • NAME: для обычных файлов показывает имя точки монтирования и файловой системы, в которой находится файл. Для других типов файлов здесь указываются специфичные для них данные, подробности будут даны ниже.

Колонка FD

Дескриптор файла в столбце FD может быть одним из многих вариантов; на странице руководства они перечислены все:

man lsof

Запись в столбце FD может состоять из трёх частей: дескриптор файла, символ режима и символ блокировки.

Некоторые популярные файловые дескрипторы:

  • cwd: текущий рабочий каталог.
  • err: информация об ошибке FD (см. столбец NAME).
  • ltx: текст разделяемой библиотеки (код и данные).
  • m86: файл сопоставления DOS Merge.
  • mem: файл с отображением в памяти.
  • mmap: устройство с отображением в памяти.
  • pd: родительский каталог.
  • rtd: корневой каталог.
  • txt: текст программы (код и данные)

Символ режима может быть одним из следующих:

  • r: доступ для чтения.
  • w: доступ для записи.
  • u: Доступ для чтения и записи.
  •  : [символ пробела], если режим неизвестен и нет символа блокировки.
  • -: режим неизвестен и есть символ блокировки.

Символ блокировки может быть одним из:

  • r: Блокировка чтения на часть файла.
  • R: Блокировка чтения на весь файл.
  • w: Блокировка записи для на часть файла.
  • W: Блокировка записи для на весь файл.
  • u: Блокировка чтения и записи любой длины.
  • U: неизвестный тип блокировки.
  •  : [символ пробела]. Нет блокировки.

Колонка TYPE

В столбце TYPE может отображаться более 70 записей. Далее перечислены только некоторые из часто встречающихся записей:


  • REG: Обычный файл файловой системы.
  • DIR: Директория.
  • FIFO: Специальный файл FIFO (First In First Out).
  • CHR: Специальный символьный файл.
  • BLK: Специальный блочный файл.
  • INET: Интернет-сокет.
  • unix: Доменный сокет UNIX.
  • IPv4: IPv4 сокет.
  • IPv6: Файлы IPv6 сети — даже если её адрес IPv4 преобразован в IPv6 адрес.
  • sock: Сокет неизвестного домена.
  • DEL: Указатель Linux для удалённого файла.
  • LINK: Файл символьной ссылки.
  • PIPE: Труба (pipe) — способ обмена данными между процессами.

Колонка NAME

В этом поле может быть:

  • имя точки монтирования и файловой системы, в которой находится файл;
  • или имя файла, указанное в опции имён (после разрешения всех символических ссылок);
  • или имя символьного специального или блочного специального устройства;
  • или локальный и удалённый Интернет-адреса сетевого файла; после имени локального хоста или IP-адреса ставится двоеточие (':'), порт, «->» и удалённый адрес, состоящий из двух частей; IP-адреса могут быть представлены в виде чисел или имён, в зависимости от опций +|-M, -n и -P; номера IPv6, разделённые двоеточиями, заключаются в квадратные скобки; адреса IPv4 INADDR_ANY и IPv6 IN6_IS_ADDR_UNSPECIFIED, а также нулевые номера портов представлены звёздочкой ('*'); за адресом назначения UDP может следовать количество времени, прошедшее с момента отправки последнего пакета в пункт назначения; за удалёнными адресами TCP, UDP и UDPLITE может следовать информация TCP/TPI в скобках, такая как: состояние (например, «(ESTABLISHED)», «(Unbound)»), размеры очереди и размеры окон (не для всех диалектов) — вывод в духе того, что сообщает netstat; см. описание опции -T или описание поля TCP/TPI в ВЫХОДЕ ДЛЯ ДРУГИХ ПРОГРАММ для получения дополнительной информации о состоянии, размере очереди и размере окна;
  • или адрес или имя сокета домена UNIX, возможно, включая имя устройства клонирования потока, имя пути объекта файловой системы, локальные и внешние адреса ядра, информацию о паре сокетов и связанный адрес vnode;
  • или имена локальной и удалённой точек монтирования файла NFS;
  • или «STR», за которым следует имя потока;
  • или имя символьного устройства потока, за которым следует «->» и имя потока, или список имён потоковых модулей, разделённых знаком «->»;
  • или другое значение, характерное обычно для определённых ОС;

Как видеть процессы, которые открыли файл

Чтобы увидеть процессы, открывшие определённый файл, укажите имя файла в качестве параметра для lsof. Например, чтобы увидеть процессы, которые открыли файл /dev/sda, используйте эту команду:

lsof /dev/sda

Пример вывода:

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
doublecmd 1982 mial  cwd    DIR    8,0     4096 32768001 /mnt/disk_d/Share

Как вы можете знать (а если не знаете, то смотрите статью «Структура директорий Linux. Важные файлы Linux»), файл /dev/sda является жёстким диском. Приведённая выше команда поможет найти процесс, который не даёт отмонтировать (отсоединить) диск.

Можно проверить, какой командой открыты обычные файлы, например:

lsof 'Documents/Linux.odt'

Вывод:

COMMAND    PID USER   FD   TYPE DEVICE SIZE/OFF    NODE NAME
soffice.b 3686 mial   92uW  REG  259,2    19826 5390035 Documents/Linux.odt

Видно, что файл открыт пользователем mial, это обычный файл (REG) и что он открыт приложением soffice.b (на самом деле приложение soffice.bin, но его имя здесь не целиком).

Чтобы вывести полное имя, используйте опцию +c, например:

lsof +c 15 /home/mial/Вирус.odt


Аналогично можно проверить, открыты (запущены) ли исполнимые файлы, например, для проверки, запущен ли файл /bin/bash:

sudo lsof /bin/bash

Как посмотреть все файлы, открытые в определённом каталоге

Чтобы увидеть файлы, которые были открыты из каталога, и процессы, которые их открыли, передайте каталог в lsof в качестве параметра. Для этого используйте опцию +D КАТАЛОГ.

Чтобы увидеть все файлы, которые открыты в каталоге /var/log/, используйте эту команду:

sudo lsof +D /var/log/

lsof отвечает списком всех открытых файлов в этом каталоге.

Чтобы увидеть все файлы, которые были открыты из каталога /home, используйте следующую команду:

sudo lsof +D /home

Файлы, которые были открыты из каталога /home. Обратите внимание, что в некоторых столбцах данные поместились не полностью.


Как показать только обычные файлы

Чтобы показать обычные файлы и директории и исключить все другие виды файлов (устройства, сокеты и т. д.) выполните следующую команду:

sudo lsof /

Как увидеть файлы, которые открыты указанной программой или командой

В столбце COMMAND указано имя исполнимого файла, который открыл файл. Чтобы увидеть файлы, которые были открыты определенным процессом, используйте параметр -c КОМАНДА. Обратите внимание, что вы можете указать более одного поискового запроса для lsof одновременно.

sudo lsof -c ssh -c systemd

lsof выведет список файлов, которые были открыты любым из процессов, представленных в командной строке.

Как посмотреть файлы, открытые определённым пользователем

Чтобы ограничить отображение файлами, которые были открыты определенным пользователем, используйте параметр -u ПОЛЬЗОВАТЕЛЬ. В этом примере мы рассмотрим файлы, которые были открыты процессами, которые принадлежат или запускаются от имени mial.

sudo lsof -u mial

Будут перечисленные все файлы, которые были открыты от имени пользователя mial. Они включают в себя файлы, которые были открыты, например, средой рабочего стола, или просто в результате входа mial.

Как исключить файлы, открытые определённым пользователем

Чтобы исключить файлы, которые были открыты пользователем, используйте оператор ^. Исключение пользователей из списка облегчает поиск интересующей вас информации. Вы должны использовать опцию -u, как и раньше, и добавить символ ^ в начале имени пользователя.

sudo lsof -u ^mial

Отрицание (поиск любых значений, кроме приведённых) можно применять с любыми опциями, для которых можно указать какое-либо значение, то есть с именами пользователей, именами команд, идентификаторами процессов, папками и т.д.

Например, чтобы показать все файлы, которые были открыты в директории /home, но которые открыты процессами, не принадлежащими пользователю mial:

sudo lsof +D /home -u ^mial

Как найти файлы, которые открыты указанным процессом

Чтобы вывести список файлов, которые были открыты определенным процессом, используйте параметр -p ПРОЦЕСС и укажите идентификатор процесса в качестве параметра.


sudo lsof -p 9099

Все файлы, которые были открыты по указанному вами идентификатору процесса, перечислены для вас.

Как узнать идентификаторы процессов, которые открыли файл

Чтобы увидеть идентификаторы процессов, которые открыли конкретный файл, используйте параметр -t ФАЙЛ.

sudo lsof -t /usr/share/mime/mime.cache

Идентификаторы процесса, открывших файл, отображаются в виде простого списка.

Как вывести размер открытых файлов

Для показа размера используйте опцию -s:

lsof -s

Для сортировки по размеру обычных файлов выполните следующую команду:

lsof / -s | sort -rnk 7

Как узнать какие процессы и сколько потребляют памяти в области Buff/Cache

Buffer/cache используются виртуальными файловыми системами, а также для оптимизации чтения/записи на диск, то есть файлы, которые уже были прочитаны с диска, размещены там для ускоренного доступа.

Следующая команда сортирует открытые файлы по размеру — именно они и занимают место в buffer/cache:

lsof -s | sort -rnk 7 | less

Buffer/cache потребляет не столько ядро, сколько всякие браузеры, офисные программы, графическое окружение, программы, имеющие большие логи и т. п. То есть все программы, которые открывают много файлов и/или большие файлы и держат их открытыми.

Как комбинировать условия поиска lsof (логические И и ИЛИ)

Давайте выведем файлы, которые были открыты пользователем mial и которые связаны с процессами systemd. Мы знаем, что можем предоставить более одного элемента поиска в командной строке, поэтому это должно быть легко.

sudo lsof -u mial -c systemd

Теперь давайте посмотрим на вывод lsof. Это не выглядит правильно; в выводе есть записи, которые были запущены пользователем root.

Это не то что мы ожидали. Что произошло?

Если вы предоставите несколько поисковых терминов, lsof вернёт любой файл, который соответствует первому поисковому запросу или второму поисковому запросу и так далее. Другими словами, она выполняет поиск ИЛИ.

Чтобы lsof выполняла поиск И, используйте опцию -a. Это означает, что будут перечислены только те файлы, которые соответствуют первому поисковому запросу, второму поисковому запросу и т. д.

Давайте попробуем это снова и используем опцию -a.

sudo lsof -u mial -c systemd -a

Теперь каждый файл в списке — это файл, который был открыт пользователем mial или от его имени и связан с systemd.

Обратите внимание, что два условия, одно из которых содержит отрицание (^) обрабатываются как логическое И:

sudo lsof +D /home -u ^mial

Но если требуется логическое И, то лучше взять за правило всегда использовать опцию -a, поскольку так команда становиться более однозначной:

sudo lsof +D /home -u ^mial -a

и в случае добавления третьего условия поиска она будет работать как ожидается:

sudo lsof -u mial +D /home/mial -c^chromium -a

Автоматическое обновление выводимой информации lsof

Чтобы перевести lsof в режим повтора, мы можем использовать опцию +r СЕКУНДЫ или её вариант -r СЕКУНДЫ. Опцию повторения можно применить двумя способами: +r или -r. Мы также должны добавить количество секунд, которое мы хотим, чтобы lsof ожидал перед обновлением дисплея.

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

С опцией -r это будет продолжаться пока вы не нажмете Ctrl+c. В формате +r программа будет продолжаться до тех пор, пока не будет получен пустой результат, или пока вы не нажмете Ctrl+c.

sudo lsof -u mial -c ssh -a -r5

Обратите внимание на пунктирную линию (=======) внизу списка. Она отделяет каждое новое отображение данных при обновлении вывода.

Отображение файлов, связанных с подключениями к Интернету

Опция -i позволяет просматривать файлы, открытые процессами, связанными с сетевыми и Интернет-соединениями.

sudo lsof -i

Отображаются все файлы, связанные с сетевыми подключениями и подключению к Интернету.

Если вы не хотите, чтобы цифровые обозначения портов заменялись на имена (например, http вместо 80), то добавьте опцию -P:

sudo lsof -i -P

Отображение файлов, связанных с подключениями к Интернету, по идентификатору процесса

Чтобы увидеть файлы, открытые подключениями к Интернету, которые связаны с определенным идентификатором процесса, добавьте параметр -p PID и параметр -a.

Здесь мы ищем файлы, открытые через Интернет или сетевое соединение, с помощью процесса с идентификатором 606.

sudo lsof -i -a -p 606

Отображение файлов, связанных с Интернет-подключениями и командами

Мы можем использовать опцию -c КОМАНДА для поиска файлов, открытых определёнными процессами. Чтобы найти файлы, которые были открыты через Интернет или сетевые подключения, связанные с процессом ssh, используйте следующую команду:

lsof -i -a -c ssh

Отображение файлов, связанных с Интернет-подключениями и портами

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

Здесь мы просим lsof перечислить файлы, которые были открыты сетевым или Интернет-соединением с использованием порта 22.

lsof -i :22

Как показать сокеты только для определённого протокола

Мы можем попросить lsof показать файлы, которые были открыты процессами, связанными с сетевыми и Интернет-соединениями, которые используют определённый протокол. Мы можем выбрать из TCP, UDP и SMTP. Давайте использовать протокол TCP и посмотрим, что мы получим. Если вас интересуют только сетевые подключения на TCP протоколе или UDP протоколе, то вы можете использовать следующие команды:

lsof -i TCP
# или:
lsof -i UDP

Протоколы можно писать как прописными буквами, так и строчными:

sudo lsof -i tcp

Как узнать, какой процесс или служба прослушивают порт

Чтобы узнать, какая программа прослушивает определённый порт, выполните команду вида:

lsof -i :ПОРТ

Например, чтобы увидеть процесс, который открыл 80й порт:

lsof -i :80

Если вы хотите проверить занятость порта на определённом протоколе (TCP или UDP), то укажите интересующий протокол перед номером порта:

lsof -i TCP:22
# или:
lsof -i UDP:53

Как просмотреть только IPv4 или IPv6 соединения

IPv6 — это шестая, новая версия протокола IP.

Чтобы вывести открытые файлы сетевых соединений только для IPv4 выполните команду:

sudo lsof -i 4

Чтобы показать открытые файлы только типа IPv6 выполните:

sudo lsof -i 6

Как просмотреть сетевые соединения в диапазоне портов

Если нужно увидеть все запущенные процессы, которые открыли файлы TCP портов в диапазоне 1-1024, то выполните команду:

lsof -i TCP:1-1024

Кроме диапазона портов через дефис, можно указать несколько портов или их диапазонов через запятую:

lsof -i TCP:1-1024,8000-9000,10000

Как увидеть сетевые подключения определённого хоста

У каждого сетевого соединения есть исходный узел и пункт назначения, чтобы увидеть соединения, которые относятся только к определённому хосту, выполните команду вида:

lsof -i @ХОСТ

Например, я хочу просмотреть только сетевые соединения для локального компьютера с именем HackWare, тогда команда следующая:

lsof -i @HackWare

Если я хочу увидеть соединения с сайтом suip.biz, то команда такая:

lsof -i @suip.biz

В качестве хоста можно указывать не только имена сайтов или хостов, но и IP адрес.

Сочетание фильтров сетевых соединений

Можно использовать все фильтры сразу в команде вида:

lsof -i ПРОТОКОЛ@ХОСТ:ПОРТ

Пример:

lsof -i TCP@suip.biz:1-4000

Как остановить всю активность определённого пользователя

Иногда нужно убить все процессы определённого пользователя. Ниже команда, которая закроет все процессы пользователя mial:

sudo kill -9 `sudo lsof -t -u mial`

Поиск с использованием регулярных выражений программ, открывших файлы

В фильтрах lsof вы можете использовать регулярные выражения.

В следующем примере будут найдены все файлы, открытые процессом, имя которого состоит ровно из четырёх символов и третьим символом в имени является буква «o».

lsof -c /^..o.$/i

А этот пример найдёт все файлы, открытые процессом, имя которого состоит ровно из четырёх символов:

lsof -c /^....$/i

Основы команды lsof

Мы рассмотрели только самые популярные примеры использования команды lsof. Огромную документацию по этой программе с описанием всех опций вы найдёте в её справочной странице:

man lsof

Рекомендуемые статьи:

Оставить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *