- Изучаем процессы в Linux
- Содержание
- Введение
- Атрибуты процесса
- Жизненный цикл процесса
- Рождение процесса
- Состояние «готов»
- Состояние «выполняется»
- Перерождение в другую программу
- Состояние «ожидает»
- Состояние «остановлен»
- Завершение процесса
- Состояние «зомби»
- Забытье
- Благодарности
- Работа с процессами в Linux
- Список процессов
- Как в Linux найти, кто использует файл
- Утилита lsof — инструмент администратора
- Для чего служит команда lsof
- Опции команды
- Применение команды lsof
- Пример 1. Кто работает с файлом или каталогом?
- Пример 2. Какой процесс использует данный файл?
- Пример 3. Какие ресурсы использует процесс?
- Пример 4. С какими файлами работает пользователь?
- Пример 5. Кто подключился к вашему компьютеру?
- Пример 6. Кто открыл файлы по NFS?
- Пример 7. Наблюдаем за процессом копирования
- Заключение
Изучаем процессы в Linux
В этой статье я хотел бы рассказать о том, какой жизненный путь проходят процессы в семействе ОС Linux. В теории и на примерах я рассмотрю как процессы рождаются и умирают, немного расскажу о механике системных вызовов и сигналов.
Данная статья в большей мере рассчитана на новичков в системном программировании и тех, кто просто хочет узнать немного больше о том, как работают процессы в Linux.
Всё написанное ниже справедливо к Debian Linux с ядром 4.15.0.
Содержание
Введение
Системное программное обеспечение взаимодействует с ядром системы посредством специальных функций — системных вызовов. В редких случаях существует альтернативный API, например, procfs или sysfs, выполненные в виде виртуальных файловых систем.
Атрибуты процесса
Процесс в ядре представляется просто как структура с множеством полей (определение структуры можно прочитать здесь).
Но так как статья посвящена системному программированию, а не разработке ядра, то несколько абстрагируемся и просто акцентируем внимание на важных для нас полях процесса:
- Идентификатор процесса (pid)
- Открытые файловые дескрипторы (fd)
- Обработчики сигналов (signal handler)
- Текущий рабочий каталог (cwd)
- Переменные окружения (environ)
- Код возврата
Жизненный цикл процесса
Рождение процесса
Только один процесс в системе рождается особенным способом — init — он порождается непосредственно ядром. Все остальные процессы появляются путём дублирования текущего процесса с помощью системного вызова fork(2) . После выполнения fork(2) получаем два практически идентичных процесса за исключением следующих пунктов:
- fork(2) возвращает родителю PID ребёнка, ребёнку возвращается 0;
- У ребёнка меняется PPID (Parent Process Id) на PID родителя.
После выполнения fork(2) все ресурсы дочернего процесса — это копия ресурсов родителя. Копировать процесс со всеми выделенными страницами памяти — дело дорогое, поэтому в ядре Linux используется технология Copy-On-Write.
Все страницы памяти родителя помечаются как read-only и становятся доступны и родителю, и ребёнку. Как только один из процессов изменяет данные на определённой странице, эта страница не изменяется, а копируется и изменяется уже копия. Оригинал при этом «отвязывается» от данного процесса. Как только read-only оригинал остаётся «привязанным» к одному процессу, странице вновь назначается статус read-write.
Состояние «готов»
Сразу после выполнения fork(2) переходит в состояние «готов».
Фактически, процесс стоит в очереди и ждёт, когда планировщик (scheduler) в ядре даст процессу выполняться на процессоре.
Состояние «выполняется»
Как только планировщик поставил процесс на выполнение, началось состояние «выполняется». Процесс может выполняться весь предложенный промежуток (квант) времени, а может уступить место другим процессам, воспользовавшись системным вывозом sched_yield .
Перерождение в другую программу
В некоторых программах реализована логика, в которой родительский процесс создает дочерний для решения какой-либо задачи. Ребёнок в данном случае решает какую-то конкретную проблему, а родитель лишь делегирует своим детям задачи. Например, веб-сервер при входящем подключении создаёт ребёнка и передаёт обработку подключения ему.
Однако, если нужно запустить другую программу, то необходимо прибегнуть к системному вызову execve(2) :
или библиотечным вызовам execl(3), execlp(3), execle(3), execv(3), execvp(3), execvpe(3) :
Все из перечисленных вызовов выполняют программу, путь до которой указан в первом аргументе. В случае успеха управление передаётся загруженной программе и в исходную уже не возвращается. При этом у загруженной программы остаются все поля структуры процесса, кроме файловых дескрипторов, помеченных как O_CLOEXEC , они закроются.
Как не путаться во всех этих вызовах и выбирать нужный? Достаточно постичь логику именования:
- Все вызовы начинаются с exec
- Пятая буква определяет вид передачи аргументов:
- l обозначает list, все параметры передаются как arg1, arg2, . NULL
- v обозначает vector, все параметры передаются в нуль-терминированном массиве;
- Далее может следовать буква p, которая обозначает path. Если аргумент file начинается с символа, отличного от «/», то указанный file ищется в каталогах, перечисленных в переменной окружения PATH
- Последней может быть буква e, обозначающая environ. В таких вызовах последним аргументом идёт нуль-терминированный массив нуль-терминированных строк вида key=value — переменные окружения, которые будут переданы новой программе.
Семейство вызовов exec* позволяет запускать скрипты с правами на исполнение и начинающиеся с последовательности шебанг (#!).
Есть соглашение, которое подразумевает, что argv[0] совпадает с нулевым аргументов для функций семейства exec*. Однако, это можно нарушить.
Любопытный читатель может заметить, что в сигнатуре функции int main(int argc, char* argv[]) есть число — количество аргументов, но в семействе функций exec* ничего такого не передаётся. Почему? Потому что при запуске программы управление передаётся не сразу в main. Перед этим выполняются некоторые действия, определённые glibc, в том числе подсчёт argc.
Состояние «ожидает»
Некоторые системные вызовы могут выполняться долго, например, ввод-вывод. В таких случаях процесс переходит в состояние «ожидает». Как только системный вызов будет выполнен, ядро переведёт процесс в состояние «готов».
В Linux так же существует состояние «ожидает», в котором процесс не реагирует на сигналы прерывания. В этом состоянии процесс становится «неубиваемым», а все пришедшие сигналы встают в очередь до тех пор, пока процесс не выйдет из этого состояния.
Ядро само выбирает, в какое из состояний перевести процесс. Чаще всего в состояние «ожидает (без прерываний)» попадают процессы, которые запрашивают ввод-вывод. Особенно заметно это при использовании удалённого диска (NFS) с не очень быстрым интернетом.
Состояние «остановлен»
В любой момент можно приостановить выполнение процесса, отправив ему сигнал SIGSTOP. Процесс перейдёт в состояние «остановлен» и будет находиться там до тех пор, пока ему не придёт сигнал продолжать работу (SIGCONT) или умереть (SIGKILL). Остальные сигналы будут поставлены в очередь.
Завершение процесса
Ни одна программа не умеет завершаться сама. Они могут лишь попросить систему об этом с помощью системного вызова _exit или быть завершенными системой из-за ошибки. Даже когда возвращаешь число из main() , всё равно неявно вызывается _exit .
Хотя аргумент системного вызова принимает значение типа int, в качестве кода возврата берется лишь младший байт числа.
Состояние «зомби»
Сразу после того, как процесс завершился (неважно, корректно или нет), ядро записывает информацию о том, как завершился процесс и переводит его в состояние «зомби». Иными словами, зомби — это завершившийся процесс, но память о нём всё ещё хранится в ядре.
Более того, это второе состояние, в котором процесс может смело игнорировать сигнал SIGKILL, ведь что мертво не может умереть ещё раз.
Забытье
Код возврата и причина завершения процесса всё ещё хранится в ядре и её нужно оттуда забрать. Для этого можно воспользоваться соответствующими системными вызовами:
Вся информация о завершении процесса влезает в тип данных int. Для получения кода возврата и причины завершения программы используются макросы, описанные в man-странице waitpid(2) .
Передача argv[0] как NULL приводит к падению.
Бывают случаи, при которых родитель завершается раньше, чем ребёнок. В таких случаях родителем ребёнка станет init и он применит вызов wait(2) , когда придёт время.
После того, как родитель забрал информацию о смерти ребёнка, ядро стирает всю информацию о ребёнке, чтобы на его место вскоре пришёл другой процесс.
Благодарности
Спасибо Саше «Al» за редактуру и помощь в оформлении;
Спасибо Саше «Reisse» за понятные ответы на сложные вопросы.
Они стойко перенесли напавшее на меня вдохновение и напавший на них шквал моих вопросов.
Источник
Работа с процессами в Linux
Список процессов
Вывести на экран список текущих процессов, запущенных пользователем, можно командой:
Чтобы посмотреть список всех процессов с дополнительной информацией, вводим:
Мы увидим, примерно, следующее:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 661 0.0 0.0 4072 8 tty1 Ss+ Jul03 0:00 /sbin/mingetty
root 662 0.0 0.0 4072 8 tty2 Ss+ Jul03 0:00 /sbin/mingetty
root 16355 0.0 0.0 171636 3308 pts/0 S 15:46 0:00 sudo su
root 16366 0.0 0.0 140896 1556 pts/0 S 15:46 0:00 su
root 16368 0.0 0.0 108316 1944 pts/0 S 15:46 0:00 bash
root 18830 0.0 0.0 110244 1172 pts/0 R+ 16:20 0:00 ps u
- USER — учетная запись пользователя, от которой запущен процесс.
- PID — идентификатор процесса.
- %CPU — потребление процессорного времени в процентном эквиваленте.
- %MEM — использование памяти в процентах.
- VSZ — Virtual Set Size. Виртуальный размер процесса (в килобайтах).
- RSS — Resident Set Size. Размер резидентного набора (количество 1K-страниц в памяти).
- TTY — терминал, из под которого был запущен процесс.
- STAT — текущее состояние процесса. Могут принимать значения:
- R — выполнимый процесс;
- S — спящий;
- D — в состоянии подкачки на диске;
- T — остановлен;
- Z — зомби.
- W — не имеет резидентных страниц;
- Дмитрий Моск — IT-специалист.
Настройка серверов, компьютерная помощь.
Как управлять процессами в операционной системе Linux
Источник
Как в Linux найти, кто использует файл
Оригинал: How to Find Out Who is Using a File in Linux
Автор: Aaron Kili
Дата публикации: 29 марта 2019 г.
Перевод: В.Костромин
Дата перевода: 13 мая 2020 г.
В этой статье мы расскажем, как узнать, кто использует тот или иной файл в Linux. Это позволит вам найти системного пользователя или процесс, который использует открытый файл.
Мы можем использовать команду lsof, чтобы узнать, использует ли кто-то файл, и если да, то кто именно. Эта команда обращается к памяти ядра в поиске открытых файлов и выводит список всех открытых файлов. Открытый файл может быть обычным файлом данных, каталогом, специальным файлом устройства, символьным файлом устройства, потоком, сетевым файлом или относиться к какому-то еще типу файлов — потому что в Linux все является файлом.
Lsof используется файловой системой, чтобы определить, кто использует какие-либо файлы в этой файловой системе. Вы можете запустить команду lsof в файловой системе Linux, и выходные данные идентифицируют владельца и информацию о процессах, использующих файл, как показано в следующем листинге выходных данных.
Список всех открытых в Linux файлов
Чтобы вывести список файлов, открытых для конкретного пользователя, выполните следующую команду:
Список файлов, открытых конкретным пользователем (при использовании в вашей системе замените tecmint действительным именем пользователя)
Еще одно важный случай применения команды lsof — определение процесса, использующего определенный порт. Например, чтобы определить, какой процесс использует порт 80, можно воспользоваться следующим вариантом запуска команды lsof.
Определение процесса, прослушивающего порт
Важное замечание: Поскольку lsof в поисках открытых файлов обращается к памяти ядра, быстрые изменения в памяти ядра могут привести к непредсказуемому результату. Это один из главных недостатков использования команды lsof.
За дополнительной информацией обращайтесь к странице руководства lsof man:
На этом все! В этой статье мы объяснили, как узнать, кто использует тот или иной файл в Linux. Мы показали, как определить владельца и информацию о процессах, использующих открытый файл.
Об авторе
Aaron Kili — энтузиаст Linux и свободного ПО, системный администратор, веб-разработчик и в настоящее время создатель контента для TecMint, который любит работать с компьютерами и твердо верит в обмен знаниями.
Вы можете найти на нашем сайте более подробные статьи о команде lsof:
Источник
Утилита lsof — инструмент администратора
Во время работы в Linux мне иногда приходилось сталкиваться с одной проблемкой. Установил я, скажем, диск CD-ROM в привод, смонтировал его, потом в процессе работы запустил кучу разных приложений, про CD в приводе уже и забыл. Затем мне потребовалось что-то прочитать с другого диска, я жму на кнопочку извлечения диска на панели CD-ROM, однако реакции никакой не следует. А в ответ на команду выдается такое сообщение: Приложений у меня открыто много, так что я уже и не помню, какое из них открыло файлы на CD и тем самым препятствует размонтированию диска. И иногда даже последовательный перебор всех открытых окон не позволял понять, что же надо закрыть. Я помнил, правда, что есть статья С.Лапшанского с описанием решения аналогичной проблемы, да все руки не доходили заняться этим. Но вот надоело мне в конце концов все время наступать на одни и те же грабли, и решил я разобраться с CD-ROM и его размонтированием. Вначале просмотрел я свой каталог на сайте http://rus-linux.net и статью Лапшанского [2] разыскал, но оказалось, что рассматривается в ней аналогичная проблема во FreeBSD, и решается она с помощью утилиты fstat . Я, конечно, попытался вызвать эту команду в своей системе на основе дистрибутива ASP Linux 7.3, но такой команды в моей системе не обнаружилось. Команда man fstat сообщила, что есть такой системный вызов fstat , который выдает информацию об указанном файле, но писать собственную утилиту на основе этого системного вызова мне, прямо признаюсь, не по силам.
Сейчас я даже уже и не вспомню, откуда я это знал, но где-то в глубинах подсознания мелькнула мысль, что для решения этой проблемы можно использовать утилиту lsof . Кстати, один из читателей моей книги [3] в своем отзыве на книгу в качестве недостатка указал на то, что эта утилита в книге не описана. Я и решил попытаться применить lsof для решения своей задачи, и начал, естественно, с изучения справки, выдаваемой командой man lsof . А кроме того, поискал информацию в Интернет и нашел статьи 5. Все эти материалы и послужили основой для настоящей статьи.
Для чего служит команда lsof
Относительно lsof справка man как раз сообщает, что lsof есть сокращение от LiSt of Open Files, и что утилита эта служит для вывода информации о том, какие файлы используются теми или иными процессами. Причем утилита эта имеется в очень многих версиях и диалектах UNIX, включая Linux версии 2.1.72 и выше, а также в HP-UX, AIX, NextStep, Apple Darwin для Power Macintosh, SCO UnixWare, Solaris, FreeBSD, NetBDS, OpenBSD и так далее.
Создателем программа lsof является Victor A. Abell, его домашняя страничка расположена по адресу http://people.freebsd.org/
abe/ , где вы можете найти исходные коды программы. Их можно также скачать с FTP-сайта ftp://vic.cc.purdue.edu/pub/tools/unix/lsof. О том, как скомпилировать и установить программу, вы можете прочитать в статье [8].
Если запустить эту утилиту без параметров, выдается информация о всех работающих процессах и открытых ими файлах. Даже в моей системе с одним пользователем эта команда выдала 2344 строки текста. Попробуй проанализируй эту массу информации! Но давайте взглянем хотя бы на несколько строк ее вывода, чтобы на этом примере понять, какую же информацию она выдает.
Кстати, если вы будете экспериментировать, имейте в виду, что будучи запущенной простым пользователем, эта команда выдает информацию только о процессах, запущенных этим пользователем. Поэтому во многих случаях вы можете не получить от нее никакого ответа. Если вы хотите получить вразумительный ответ на любой свой запрос, ее необходимо запускать от имени root-а (можно воспользоваться следующей формой запуска sudo lsof ). Кроме того, команда отрабатывает достаточно медленно, так что будьте терпеливы и не щелкайте раньше времени + — программа не зависла, просто идет поиск информации.
А теперь смотрим листинг 1 (или результат работы программы на вашем экране).
Листинг 1. Вывод команды lsof.
Как видите, один и тот же процесс открывает много файлов, каждому из которых соответствует строка в выводе lsof . В начале строки указывается имя процесса, его идентификатор, имя пользователя, запустившего процесс. В столбце FD стоит номер файлового дескриптора или одна из следующих буквенных комбинаций (я не берусь корректно перевести на русский язык некоторых из расшифровок этих сокращений, так что привожу их в том виде, как они выдаются справочной системой):
- cwd — текущий рабочий каталог;
- ltx — текст разделяемой библиотеки;
- mxx — hex memory-mapped type number xx.
- m86 — DOS Merge mapped file;
- mem — файл, загруженный в память (memory-mapped file), чаще всего – библиотека,
- mmap — memory-mapped device;
- pd — родительский каталог;
- rtd — корневой каталог;
- txt – текст программы (код и данные);
- v86 — VP/ix mapped file.
Номер файлового дескриптора сопровождается символом, указывающим режим, в котором файл был открыт:
- r — файл открыт для чтения;
- w – файл открыт для записи;
- u — файл открыт для чтения и для записи;
- пробел – режим доступа неизвестен и файл не блокирован;
- ‘-’ — режим доступа неизвестен, но на файл установлена блокировка.
В последнем случае за дефисом следует еще один символ, определяющий тип блокировки (подробнее смотри man lsof ).
В следующем столбце указан тип файла. Чаще других встречаются файлы одного из следующих типов: REG — обычный файл, DIR — каталог, BLK — файл блочного устройства, CHR — файл символьного устройства, LINK — файл символической ссылки, INET – Internet-сокет, UNIX – доменный сокет UNIX. Но на справочной странице список типов гораздо обширнее.
Вслед за типом указывается устройство, на котором расположен файл, размер файла, номер индексного дескриптора и имя файла.
Опции команды
Поскольку просматривать вывод команды lsof, запущенной без параметров, достаточно неудобно, можно сократить объем выдаваемых данных, конкретизировав ваш запрос, что достигается за счет использования опций. Опций у этой утилиты довольно много и большинство из них действует по принципу ограничения вывода. Если вы указываете, например, опцию -U, то будут выведены только данные о сокетах UNIX, а все другие файлы игнорируются. Если указать две или более опций, то их действие определяется правилом ИЛИ, то есть выводится информация, определяемая каждой из опций. Например, команда
/usr/sbin/lsof -U -u kos
выдаст данные о всех открытых UNIX-сокетах и всех файлах, принадлежащих процессам, запущенным пользователем “kos”.
Если же необходимо скомбинировать действие опций по принципу логического И, то это делается путем специальной опции -a. Например, команда
/usr/sbin/lsof -a -U -u kos
выдаст список только сокетов UNIX, принадлежащих процессам, владельцем которых является пользователь “kos”’. Обратите внимание на то, что опция -a стоит не между объединяемыми ею другими опциями. Впрочем, ее можно ставить где угодно, все равно все перечисленные в командной строке опции будут работать по принципу “логическое И”.
Но если указывается, например, несколько однотипных опций, то вначале к ним применяется операция логического ИЛИ, а затем уже работает опция -a. Пример: по команде
/usr/sbin/lsof -i@aaa.bbb -i@ccc.ddd -a -ufff,ggg
будет выведен список файлов, принадлежащих ЛИБО пользователю “fff”, ЛИБО пользователю “ggg” И имеющих сетевые соединения ЛИБО к хосту aaa.bbb ЛИБО к хосту ccc.ddd.
Опции команды lsof можно записывать одну за другой без пробелов, предваряя это список всего одним дефисом, то есть вместо
/usr/sbin/lsof -a -b -C
можно указать просто
Однако при этом надо побеспокоиться о том, чтобы не было неоднозначности в интерпретации опций. Но я не буду детально рассматривать возможные причины неоднозначности, если у вас возникает желание использовать эту возможность, смотрите соответствующую man-страницу.
Отмечу только, что существует ряд опций, которые позволяют изменить вывод программы lsof. Например, опция -R заставляет lsof дополнительно выводить данные об идентификаторе родительского процесса. Очень интересной может оказаться опция -F. Запущенная с этой опцией утилита lsof выдает информацию не в виде таблицы, а в виде последовательности отдельных строк. В таком случае вывод можно перенаправить на вход другой программы, которая будет каким-либо образом обрабатывать полученную информацию. После опции -F можно указать, какие именно поля будут присутствовать в выводе. Например, если командная строка имела вид
в выводе lsof будет присутствовать идентификатор процесса (p), имя команды (c), файловый дескриптор (f) и ися файла.
Применение команды lsof
Не имеет смысла повторять в статье описание всех опций этой команды, имеющееся на страничке man. Давайте ограничимся тем, что рассмотрим ее применение и использование наиболее употребительных опций на примерах конкретных ситуаций.
Пример 1. Кто работает с файлом или каталогом?
Начнем с решения той проблемы, которая была описана в начале статьи, и которая рассматривалась в упомянутой выше статье С.Лапшанского [2]. Итак, вы попытались размонтировать CD-ROM (захотели сменить диск). А в ответ получили сообщение “Device is busy”. Это означает, что какой-то процесс открыл файл, расположенный на этом устройстве. А чтобы узнать, какие файлы открыты в том или ином каталоге, служит опция +d команды lsof. Поэтому, чтобы узнать, кем занят диск, дайте команду следующего вида:
(у меня CD-ROM монтируется в каталог /mnt/cdrom). В ответ я получил такое сообщение:
Как видите, сразу становится ясно, что дисковод используется пользователем kos, причем, видимо, какой-то подкаталог каталога /mnt/cdrom открыт в одной из панелей файлового менеджера Mifnight Commander (mc).
Надо отметить, что при использовании опции +d dir выдается информация только о тех файлах и подкаталогах, которые содержатся в самом каталоге dir, а не в его подкаталогах. Для решения рассматриваемой проблемы этого вполне достаточно, потому что если обычно в выводе команды указан и файл данного каталога. Но, если вы все же захотите получить список всех открытых файлов во всех вложенных подкаталогах каталога dir, надо воспользоваться опцией +D. Попробуем, например, посмотреть, какие файлы открыты в каталоге /var/ и всех его подкаталогах. В работающей системе всегда найдутся открытые файлы из этого каталога, поэтому на этом примере очень наглядно демонстрируется разница между опциями +d и +D:
(Упомяну для точности, что символические ссылки игнорируются и поэтому в выводе этой команды не перечисляются.)
Если вы почему либо хотите указать не имя каталога или файла, а номер файлового дескриптора, вы можете воспользоваться командой lsof -f fd, где fd есть список файловых дескрипторов, разделенных запятыми. В списке можно использовать диапазоны: 1-3,5 и те буквенные сочетания, которые были упомянуты выше, например, cwd,ltx,mem.
Между прочим, когда я экспериментировал с командой lsof , выяснилось, что файловый менеджер Konqueror не “держит” устройство: несмотря на то, что в Konqueror открыт каталог, расположенный на примонтированном CD, операция размонтирования устройства выполняется без проблем. По-видимому, Konqueror (как, вероятно, и другие браузеры) скачивает файл и закрывает соединение (файл).
Пример 2. Какой процесс использует данный файл?
Приведенный пример очень похож на предыдущий, только вы получаете сведения о процессах, использующих конкретный файл.
Пример 3. Какие ресурсы использует процесс?
Вы уже видели в листинге 1, что каждый процесс открывает несколько файлов. Но когда я выполнил команду
я был поражен тем, как много файлов открыто этим процессом. Впрочем, я привел этот пример не для того, чтобы сообщить о своем удивлении. Это пример просто иллюстрирует применение опции — с string в команде lsof. Запущенная с этой опцией lsof выводит список файлов, отрытых процессами, выполняющими команды, название которых начинается строкой string (один или несколько символов).
Но строка string может соответствовать нескольким запущенным в данный момент командам. Если вы хотите конкретизировать ваш запрос, вы можете воспользоваться другой опцией: -p pid. Например:
Команда lsof -p pid выводит список файлов, открытых процессами, чьи идентификаторы (PID) находятся в списке pid, например, “3593” или “823,451” (отдельные идентификаторы разделяются запятыми, пробелы в списке недопустимы). С помощью этой команды вы сможете увидеть, например, какие библиотеки используются процессом. Номер нужного PID можно извлечь из результатов выполнения команды /usr/sbin/lsof -c string.
Аналогичным образом можно вывести список файлов, открытых процессами, чьи идентификаторы группы (PGID) находятся в разделенном запятыми списке gid. Это позволяет сделать команда lsof -g gid .
Пример 4. С какими файлами работает пользователь?
Следующий вариант запуска той же команды:
позволяет вывести список файлов, открытых всеми процессами, запущенными пользователями, чье имя или идентификатор содержится в списке names. Отдельные элементы списка разделяются запятыми, например, ”548,root” (пробелов быть не должно).
Пример 5. Кто подключился к вашему компьютеру?
Команда lsof очень полезна в том случае, когда вы хотите обеспечить безопасность работы вашего компьютера в сети. С ее помощью вы можете определить, какие порты открыты для приема входящих соединений и какая программа прослушивает каждый порт. После это можно закрыть ненужные порты, чтобы минимизировать риск проникновения в систему злоумышленника. Для того, чтобы узнать, какие процессы в данный момент прослушивают сетевые соединения, воспользуйтесь командой lsof с опцией -i :
На листинге 2 показан результат выполнения этой команды на компьютере trend в моей домашней сети, состоящей всего из двух компьютеров.
Порты, которые открыты для входящих соединений, обозначены меткой LISTEN. Метка ESTABLISHED показывает, что по данному порту соединение установлено. В листинге 2 вы можете видеть пример двух SSH-сессий. Первая сессия установлена хостом old-lin.home.kos с компьютером trend.home.kos. Она обслуживается процессом с PID 2192, который был порожден основным демоном sshd, PID 727. Процесс с PID 2464, наоборот, соответствует соединению, установленному клиентской программой ssh на компьютере trend.
Поскольку и в этом случае количество информации, выдаваемой командой lsof с опцией -i может оказаться очень велико, можно конкретизировать запрос. Для этого нужно использовать команду в следующем формате:
где после опции -i указывается еще параметр – интересующий вас порт, сервис или имя хоста. В общем случае параметр adress задается в следующем виде (квадратные скобки обозначают необязательность каждой части параметра):
Здесь “46” обозначает версию протокола IP. Цифру 6 можно указывать только в том случае, если ваше ядро поддерживает IPv6. Если не указано ни 4, ни 6, будут рассматриваться соединения по тому и другому варианту протокола. Задавать версию протокола можно указывая опцию в форме -i4 -i6 (это то же самое, что и указать просто -i). Если указывается только версия IP-протокола без указания других частей параметра address, отображаются только данные о тех процессах и файлах, которые работают по соответствующему протоколу.
Вместо “protocol” в параметре может стоять либо TCP, либо UDP (либо ничего).
“hostname” — имя хоста, а “hostaddr” — числовой адрес. В случае протокола IPv4 эта часть задается в форме десятично-точечной записи, в случае IPv6 – в форме чисел, разделенных двоеточиями и заключенных в скобки.
“service” — это название одного из сервисов, например, smtp, или список таких сервисов.
“port” — это номер порта или список таких номеров.
Чтобы сказанное стало понятнее, приведем несколько простых примеров.
В этом случае будет выдан список всех процессов, прослушивающих или установивших соединение через порт 80.
[root]# lsof -i :smtp
В этом примере будут перечислены все соединения, ассоциированные с почтовым протоколом SMTP.
[root]# lsof -i @rus-linux.net
В третьем случае будет выдан список всех входящих и исходящих соединений с хостом rus-linux.net.
[root]# lsof -i UDP@rus-linux.net:123
Эта команда покажет, какие процессы установили UDP-соединения с хостом rus-linux.net через порт 123 (ntp).
Очевидно, что указание параметра adress полезно только в том случае, когда вы заранее знаете, что именно вам нужно искать. Вы можете таким образом проверить, например, что какой-то конкретный сервис фактически работает и какой порт он прослушивает. Вы можете увидеть, подключился ли кто-то извне к вашему компьютеру по таким протоколам как SSH, Telnet, FTP или другим возможным способом.
Пример 6. Кто открыл файлы по NFS?
Если вы хотите узнать, открыты ли какие-то файлы, предоставленные удаленным пользователям по протоколу NFS, используйте опцию -N.
Пример 7. Наблюдаем за процессом копирования
Предположим, что вы решили переместить из одного каталога в другой большое количество файлов (или большой каталог целиком). И вы хотите видеть, какой именно файл перемещается в данный момент. Тут вам и может помочь утилита lsof. Для этого достаточно дать команду примерно такого вида (в этом примере предполагается, что перемещаются куда-то файлы из каталога Photo):
При этом нужно иметь в виду, что команда lsof делает как-бы “мгновенный снимок”, отображающий только лишь состояние процессов и соответствующих файлов в момент ее выполнения. Так что для “наблюдения за процессом” надо повторять ее запуск многократно. И в таком случае может оказаться полезной опция +r, которая служит для периодического повторения запуска команды через заданный промежуток времени.
Заключение
В конце статьи можно сформулировать следующий вывод: поскольку файл и процесс – два ключевых понятия в операционной системе, утилита lsof может оказаться незаменимым помощником администратора в тех случаях, когда надо разобраться, как работает система, а особенно в тех случаях, когда система скомпрометирована. И она тем полезнее, чем больше ваша система и чем больше вы с ней работаете, чем лучше вы понимаете, что она может. Когда вы освоите ее возможности, вы сможете создать отдельные скрипты для обработки тех огромных массивов информации, которые выдает эта программа. Можно, например, запускать команду lsof -i через определенные промежутки времени, чтобы сравнивать полученные данные. Если будут выявлены отличия в числе открытых процессов или другие отличия, удовлетворяющие заданному критерию, скрипт может сформировать сообщение администратору.
Мы рассмотрели только малую часть возможностей этой утилиты. Более подробную информацию ищите на соответствующей man-страничке.
Источник