Кто использует эти файлы во FreeBSD?


Майкл Лукас
перевод Станислава Лапшанского
Впервые опубликован: http://www.computerra.ru.


Однажды утром, когда мне казалось, что во всем мире не хватит кофеина что бы проснуться, я решил спрятаться от публики и разобраться со списком разнообразных мелочей требующих моего внимания. Среди прочего мне было нужно скопировать кое-какие файлы с компакт дискa на винчестер. Разумеется, для начала следовало установить необходимый диск в привод. Не правда ли нетрудно? Однако, вот незадача:
$ umount /cdrom/
umount: unmount of /cdrom failed: Device busy

Такая ошибка возникает в случае попытки размонтировать CD-ROM использующийся в этот момент. Я сидел прямо перед лицевой панелью компьютера, но не заметил ни моргания лампочки на приводе, ни шума вращающегося мотора. CD-ROM был смонтирован, но явно не использовался.

В данном случае у меня было несколько способов решения этой проблемы. Я мог перезагрузить машину, при этом раздосадовав пользователей. С одной стороны разозленные пользователи достаточно забавны, а с другой, они могут породить массу проблем. В тоже время я мог бы заняться выяснением у каждого пользователя, не использует ли он CD-ROM, однако это означало бы, необходимость вылезли из удобного кресла и, о нет, общения с людьми. В принципе я мог бы принудительно размонтировать компакт диск, но я понятия не имел насколько это может быть разрушительно для несчастного пользователя. И, наконец, я мог бы выяснить почему система считает CD-ROM занятым и персонально разобраться с виновным. Поскольку этот способ предполагает минимальный контакт с людьми, я выбрал именно его. Для выяснения того, кто и какие файлы использует, применяется утилита fstat.

Согласно странице онлайнового руководства, утилита fstat предназначена для "идентификации активных файлов". Хотя это не так заметно, но в системе UNIX любой объект является файлом. В более поздних операционных системах (типа Plan 9), реализация этой идеи достигла логического совершенства - там даже каналы и сетевые соединения представляются в виде файлов. Следовательно, имея возможность узнать список используемых в данный момент файлов, вы можете досконально выяснить, что происходит в системе. fstat делает снимок состояния системы в данный момент времени. Поскольку программы только и занимаются, что постоянно открывают и закрывают всякие файлы, каналы и сетевые соединения, результат работы fstat меняется от запуска к запуску.

Если вы напечатаете в командной строке fstat, то увидите на экране список всех используемых в системе файлов. Этот список может быть очень длинным, так как каждый процесс обычно открывает не один файл, а несколько. Мой ноутбук на котором выполняется стандартный набор "офисных" приложений, обычно содержит порядка 400 открытых файлов. На небольшом веб-сервере моего друга открыто порядка 9000 файлов. На некоторых сильно загруженных серверах это значение достигает 30 тысяч. Для того что бы жизнь не казалась вам медом, программы постоянно открывают и закрывают файлы, так что количество открытых файлов постоянно меняется. fstat делает моментальный снимок системного списка открытых файлов, так что если вы несколько раз запустите fstat вы наверняка получите разные результаты.

Вот небольшой кусочек того, что fstat выдала на экран моего ноутбука:
....
mwlucas ssh 2820 3* internet stream tcp c2ef2814
mwlucas rxvt 2819 root / 2 drwxr-xr-x 512 r
mwlucas rxvt 2819 wd /usr 846337 drwxr-xr-x 2560 r
mwlucas rxvt 2819 text /usr 802549 -rws--x--x 89092 r
mwlucas rxvt 2819 2 /dev 60 crw------- ttyv0 rw
mwlucas rxvt 2819 3* local stream c2ebdbd0 <-> c2ebd870
mwlucas rxvt 2819 4 /dev 104 crw-rw-rw- ptyp0 rw
mwlucas mozilla-bin 2725 root / 2 drwxr-xr-x 512 r
mwlucas mozilla-bin 2725 wd /usr 808118 drwxr-xr-x 1536 r
....

Вот как много информации. Что же она означает?

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

Начиная с четвертого столбца сведения становятся интереснее. Четвертый столбец может содержать или просто число, или число со звездочкой, или ключевое слово. Числом обозначается внутрипроцессовый дескриптор файла. Когда процесс открывает файлы, для организации к ним доступа, он назначает им номера (т.е. дескрипторы). Строки вывода fstat, в которых в четвертом столбце стоит число, содержат информацию о записываемых или читаемых процессом файлах.

Если в четвертом столбце находится число со звездочкой (как например в первой строке приведенного мною примера вывода fstat), то в строке описывается сокет. Это может быть UNIX-сокет, сетевой сокет или именованный канал. Строка описывающая сокет может меняться в зависимости от вида описываемого ею сокета. Сейчас мы не будем углубляться в сокеты. Утилита fstat не слишком полезна при исследовании сетевых соединений под FreeBSD, а вот в OpenBSD fstat выдает IP-адрес и номер порта открытого соединения. Вид вывода может меняться в зависимости от операционной системы. Проверьте, что выдаст fstat у вас.

Если в четвертом столбце содержится слово text, то это совсем не означает, что файл текстовый. Напротив, это значит что файл является "компьютерным" текстом, т.е. программой. (Только компьютерщики могут додуматься, что "текст" может означать "компьютерный текст"). В общем, это значит, что процесс запустил исполняемый файл.

Слово wd означает, что это рабочий каталог процесса. Рабочий каталог, это каталог, откуда запускаются программы. Например, у вас может быть запущен шелл, который просто "сидит" в каком-нибудь каталоге и ничего не делает, при этом каталог в котором он сидит является рабочим.

Четвертый столбец может содержать и другие ключевые слова, мы описали лишь самые распространенные.

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

Затем идут права доступа к файлу, в стандартном UNIX-формате.

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

И наконец нам показывают состояние чтения/записи этого файла. Если файл открыт для чтения, то вы увидите r, если для записи, то w. Сочетание rw, как вы легко можете догадаться, появляется, когда файл открыт как для чтения, так и для записи.

Все это весьма круто, остается только понять, как мы можем воспользоваться этой мощью. Вы же не сможете отсортировать из вывода fstat 400 строк отбросив ненужные 30 тысяч. Разумеется, вы можете отфильтровывать данные при помощи команды grep, но довольно часто вы просто не сможете четко сформулировать критерии поиска для grep. Для облегчения вашей участи в утилите fstat предусмотрены три мощных фильтрующих ключа. Вы можете одновременно использовать любые из них.

Ключ -f выбирает записи по точке монтирования. Если вы заинтересовались, какие файлы используются в каталоге /usr/home/mwlucas, то это подходящий случай для использования ключа -f. Обратите внимание, что fstat не ограничивается в своих поисках конкретным указанным каталогом, а ищет открытые файлы на всей файловой системе, в которой располагается каталог с данными пользователей. Таким образом команда
$ fstat -f /usr/home/mwlucas

выдаст нам список открытых файлов в файловой системе /usr, т.е. в системе, где у меня смонтирован домашний каталог.

Ключ -u фильтрует выдачу по имени пользователя. Для того что бы выяснить какие я использую в данный момент файлы, я могу запустить на выполнение команду
$ fstat -u mwlucas

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

Теперь давайте вернемся к нашим баранам. У меня есть привод компакт-дисков который кто-то занял. Кем он используется? В моей системе CD-ROM монтируется в каталог /cdrom. Для фильтрации я воспользуюсь флагом -f:
$ fstat -f /cdrom
chris tcsh 2834 wd /cdrom 141312 dr-xr-xr-x 6144 r

Используется всего один файл. Оказывается этого достаточно, что бы я не смог размонтировать диск. Файл открыт пользователем chris. Обратим внимание на четвертый столбец, в котором содержится ключевое слово "wd". Он означит, что открытый файл на самом деле является каталогом и в нем просто "сидит" какой-то интерпретатор команд. Больше никакой активности в файловой системе не проявляется.

Не следует забывать, что fstat предоставляет лишь "снимок", моментальное состояние, текущей активности в файловой системе. Для того что бы быль уверенным, что я не попал в момент, когда Крис просто ничего не делает, я мог бы попробовать запустить утилиту fstat несколько раз. Если компакт диск используется, то fstat покажет на нем еще какие-нибудь открытые файлы. В данном случае для такой проверки можно было бы просто поглядеть на лампочку CD-ROM'а. Но для нас это слишком просто. Впрочем, в любом случает, результат будет одинаков.

Я возьму телефон, позвоню Крису и скажу ему, что бы он вывел этот чертов шелл из каталога /cdrom, если он все-таки не собирается ничего в нем делать.

Может случиться, что fstat окажется свидетелем интенсивной работы совершаемой Крисом в каталоге /cdrom. В таком случае пользовательское имя Криса будет неоднократно упоминаться в записях многочисленных открытых файлов в этом каталоге. Тогда мне придется обсудить с ним способ выполнения моей и его задачи приемлемым для обоих способом.

Если Крис просто недоступен, скажем он ушел домой спать и оставил свой терминал заблокированным, я могу просто убить этот командный процессор. Утром он конечно разозлится, но мне на это наплевать. В зависимости от вашей ситуации вы можете не захотеть прибивать шелл другого пользователя, а вот я, чувствую себя замечательно, когда мне предоставляется возможность "убить" что-нибудь крисовское, поэтому именно так я и поступлю. В третьем столбце указан идентификатор процесса нашего интерпретатора, который висит где-то внутри каталога /cdrom.
$kill -1 2834
$ umount /cdrom

В принципе я мог бы насильственно размонтировать CD-ROM, воспользовавшись командой umount с ключом -f. UNIX предоставляет массу разнообразных путей решения этого вопроса. Выбирайте понравившийся.

Одной из самых неприятных особенностей утилиты fstat является то, что она выдает лишь номер записи в индексной таблице, а не нормальное имя файла. Впрочем, это не такая уж и проблема. Вы легко можете найти имя файла по его номеру при помощи команды find. Для ограничения области поиска одной точкой монтирования (т.е. файловой системой), воспользуйтесь ключом -x.

На своем ноутбуке я пользуюсь программной cvsupd (о том что это такое читайте http://www.onlamp.com/pub/a/bsd/2001/08/30/Big_Scary_Daemons.html). Если мне неожиданно захочется узнать, куда эта программа пишет свои журналы, то для выяснения я могу просмотреть сценарии ее запуска, конфигурационные файлы и страницы онлайнового руководства. Или я могу просто посмотреть какие файлы используется cvsupd.
$ ps -ax | grep cvsupd
199 ?? Is 0:00.00 cvsupd -e -C 100 -l @daemon -b /usr/local/etc/cvsup -

Итак, cvsupd выполняется под идентификатором 199.
$ fstat -p 199
cvsup cvsupd 199 root / 2 drwxr-xr-x 512 r
cvsup cvsupd 199 wd /var 40 drwxrwxrwt 512 r
cvsup cvsupd 199 text /usr 1541084 -rwxr-xr-x 891596 r
cvsup cvsupd 199 0 /dev 10 crw-rw-rw- null rw
cvsup cvsupd 199 1 /var 1759 -rw-rw-r-- 0 w
cvsup cvsupd 199 2 /var 1759 -rw-rw-r-- 0 w
cvsup cvsupd 199 3* internet stream tcp c2ef1100
cvsup cvsupd 199 4* pipe c2e07000 <-> c2e06f20 0 rw
cvsup cvsupd 199 5* pipe c2e06f20 <-> c2e07000 0 rw
cvsup cvsupd 199 6* local dgram c2ebde10 <-> c2ebe000

Поскольку мы ищем файл журнала (т.е. текстовый файл, открытый на запись - прим. переводчика), то в четвертом столбце должна быть цифра. Третья, четвертая и пятая строка являются файлами. Посмотрим, что у этих строк находится в пятом столбце. Итак, третья строка это устройство (находится в каталоге /dev), так что эта строка отпадает. У нас остались четвертая и пятая строки, которые указывают на открытое что-то, что находится внутри каталоге /var. В шестом столбце содержится номер записи в индексной таблице. В обеих строках он равен 1759.
$ find -x /var -inum 1759
/var/tmp/cvsupd.out

Мне никогда бы не пришло в голову искать файл журнала в таком месте, но к счастью fstat избавила меня от необходимости об этом догадываться.

http://www.onlamp.com/pub/a/bsd/2002/09/26/Big_Scary_Daemons.html

Обновлено: 12.03.2015