Для того, чтобы выяснить какой процесс обращается к файлу или каталогу в GNU/Linux используется утилита командной строки lsof (LiSt of Open Files).
Запуск команды без параметров повлечет вывод информации о всех запущенных процессах и открытых ими файлах. Естественно, вывод зависит от прав пользователя, под которым выполняется запуск. Но даже для ограниченного пользователя вывод может содержать несколько тысяч строк.
Для начала стоит рассмотреть: какую информацию предоставляет нам команда:
COMMAND PID TID USER FD TYPE DEVICE SIZE/OFF NODE NAME
sh 23252 user 4u CHR 5,0 70758 /dev/tty
sh 23252 user 6u CHR 136,3 5 /dev/pts/3
sh 23252 user 8w FIFO 0,5 840800 pipe
sh 23253 user cwd DIR 3,3 4096 160487 /usr/share/man
sh 23253 user rtd DIR 3,3 4096 2 /
sh 23253 user txt REG 3,3 626028 160664 /bin/bash
В первой колонке содержится команда запуска процесса или имя процесса, затем PID (идентификатор процесса), имя пользователя, с правами которого запущен процесс, FD (файловый дескриптор), тип файла, устройство, размер файла, номер индексного дескриптора и имя файла.
Часть этой информации нам не нужна, но для общего понимания стоит разобрать некоторые значения поподробнее. Для удобства я пронумерую столбцы, а типы значений в столбце представлю в виде маркированного списка:
- COMMAND - имя команды, с помошью которой был запущен процесс. Так же можно считать это именем процесса, но стоит учесть, что значение это вполне может быть не уникальным. К тому же имя процесса - это совсем не обязательно имя исполняемого файла в системе. Например, процесс с именем sh в разных системах может скрывать за собой различные командные оболочки. В нашем случае - это /bin/bash.
- PID - Этот столбец однозначно определяет процесс. Именно по этому идентификатору можно различить одноименные процессы в списке.
- TID - Идентификатор потока. Если процесс не создает дочерних потоков - столбец будет пустым.
USER - Имя пользователя, с правами которого запущен процесс.
FD - Файловый дескриптор.
Файловый дескриптор сопровождается следующими символами, обозначающими тип доступа: r/w/u/ /- - чтение/запись/запись и чтение/не известно, файл не блокирован/не известно, файл блокирован. Так же столбец FD содержит информацию о типе файлового фескриптора (описаны основные):
cwd - рабочий каталог;
err - Ошибка получения информации FD;
ltx - текст разделяемой библиотеки;
Mxx - hex-ссылка в отображаемую память;
mem - Файл в памяти;
mmap - Устройство, отображенное в памяти;
pd - Родительский каталог;
rtd - Корневой каталог;
txt - текст программы (код и данные).
- TYPE - В этом столбце указывается тип файла (описаны основные):
- REG - обычный файл;
- DIR - каталог;
- BLK - блочное устройство;
- CHR - символьное устройство;
- LINK - символическая ссылка;
- INET – Internet-сокет;
- UNIX – доменный сокет UNIX.
- DEVICE - содержит номера устройств, для символьного или блочного устройства, обычного файла или каталога.
- SIZE - размер файла или каталога.
- NODE - Номер индексного дескриптора.
- NAME - Имя файла.
Именно в столбце NAME можно увидеть - какой файл отвечает за выполнение команды в случае исполняемого файла.
В зависимости от версии и настроек системы, объем выводимых сведений может сильно отличаться.
Естественно, весь вывод команды нам просматривать ни к чему. К тому же ее выполнение занимает довольно много времени. Если нас интересует процесс использующий один конкретный файл, разумней будет использовать параметры командной строки. Весь перечень здесь приводить не стану. Разберу ситуацию с одним файлом и неизвестным процессом.
Например, можно использовать следующую команду:
lsof -F pcn /log/sample.log
Здесь:
- - F pcn - Ограничиваем вывод столбцами PID,COMMAND и NAME. Другая информация нам не интересна;
- /log/sample.log - имя исследуемого файла.
Все замечательно, но тут возникает одна загвоздка: а что, если в данный момент к файлу никто не обращается? Ведь lsof делает как бы "мгновенный снимок" и не факт, что этот снимок совпадет по времени с откртием файла неизвестным процессом.
На этот случай есть еще один параметр: -/+r [t[m<fmt>]].
Что он делает: При использовании этого параметра мы заставляем lsof перейти в режим "repeat". В этом режиме команда начинает "наблюдать" за файлом и сообщать о каждом к нему обращении.
Применять параметр можно несколькими способами:
- -r - выполнять команду бесконечно. Прерывание по Ctrl+C.
- +r - lsof ждет закрытия уже открытого файла и завершается.
- t - указывает период между "снимками" в секундах. По-умолчанию - 15
- m - указывает формат времени (см. strftime)
В нашем случае команда, наблюдающая за интересующим нас файлом будет выглядеть вот так:
lsof - F pcn -r1m%H:%M:%S /log/sample.log
Это значит, что lsof каждую секунду будет проверять - не открыл ли кто-нибудь интересующий нас файл и выводить информацию о процессе. Следует заметить - файл должен существовать на момент запуска и у пользователя должны быть права на чтение.
Между прочим, у комманды lsof имеются и более любопытные применения. Например, наблюдение за сетевыми подключениями:
Просмотреть - какие порты открыты в системе и какой процесс их использует (слушает):
/usr/sbin/lsof -i
Более подробную информацию можно получить с помощью команды man lsof.
Для lsof разработана графическая оболочка, называемая GLSOF. Ее можно получить с сайта http://glsof.sourceforge.net/.
Автор программы lsof: Victor A. Abell, его домашняя страничка: http://people.freebsd.org/~abe/.