Обзор
Инструменты ps
, top
и netstat
крутые, они дают много полезной информации о том, что происходит в системе. Но как они работают? Где берут и как получают всю эту информацию? В этой записи мы будем воссоздавать три популярных Linux инструмента вместе, вы убиваете сразу двух зайцев, изучаете и Ruby и Linux в одно время.
От переводчика: Оригинал статьи
Находим информацию о статусе
Итак, давайте попробуем ответит на вопрос “где все эти инструменты берут информацию?”. Ответ “в специальной файловой системе /proc
”. Если вы посмотрите в каталог /proc
то найдете там кучу папок и файлов, как и в любом другом каталоге на вашем компьютере. Но фишка в том, что это не настоящие файлы, это просто путь для ядра Linux предоставить данные пользователю.
Это очень удобно, потому что мы можем обрабатывать их как обычные файлы, т.е. читать без каких-либо особых инструментов. В мире Linux много вещей работают по этому принципу, если нужны еще примеры, посмотрите в директорию /dev
. Теперь, когда мы понимаем что к чему, давайте заглянем внутрь каталога /proc
.
Это лишь часть списка для примера, чтобы вы могли понять шаблон. Что означают все эти цифры? Чтож, это так называемые PIDы (Process IDs). Каждая запись содержит информацию об определенном процессе. Если вы запустите ps
то увидите что каждый процесс имеет ассоциированный идентификатор - PID:
Отсюда мы видим, что ps просто обходит все элементы /proc
и выводит информацию, которую найдет. Давайте посмотрим что находится внутри одного из пронумерованных каталогов:
Это сокращенный вывод чтобы сэкономить место, однако я настоятельно рекомендую вам посмотреть полный список. Приведем некоторые важные/интересные записи:
Запись | Описание |
---|---|
comm | имя программы |
cmdline | команда, использованная для запуска этого процесса |
environ | Environment переменные с которыми был запущен процесс |
status | Статус процесса (running, sleeping…) и использование памяти |
fd | Каталог содержащий дескрипторы файлов (open files, sockets…) |
Теперь, когда мы узнали это, можем начинать писать некоторые инструменты!
Список процессов
Давайте начнем с получения списка всех директорий в каталоге /proc
. Мы можем сделать это используя Ruby класс Dir
.
Пример:
Обратите внимание как я использовал диапазон цифр, это нужно так как в каталоге
/proc
находится много других папок, которые сейчас нас не интересуют.
Теперь можем пройтись (проитерировать) по этому списку и вывести две колонки, в первой PID, во второй имя программы.
Пример:
И примерно вот таким должен быть вывод:
Хей, выглядит так, будто мы только что сделали ps
! Да, наша программа не поддерживает все фишки оригинала, но мы сделали кое-что работающее.
Кто слушает?
Давайте теперь попробуем воспроизвести netstat
, вот так выглядит вывод этой утилиты (с флагами -ant).
Где же мы можем найти эту информацию? Если вы сказали “внутри /proc
” вы правы! Точнее она лежит в каталоге /proc/net/tcp
. Но есть маленькая проблемка, данные лежащие там не совсем похожи на вывод netstat
!
Это значит что нам придется их распарсить с помощью регулярных выражений. На данный момент давайте займемся только локальным адресом и статусом.
Вот регулярное выражение, которое я подобрал для этой задачи:
Оно позволит нам получить шестнадцатеричные значения, которые еще нужно конвертировать в десятичные. Давайте создадим класс, который будет этим заниматься.
Единственная вещь, которую осталось сделать это вывести результаты в виде таблицы.
Пример вывода:
Да, этот gem крутой!
Я только недавно нашел его и выглядит так будто теперь не придется играться с ljust
/ rjust
:)
Хватит использовать мой порт!
Вы когда-нибудь видели подобное сообщение?
Хммм… интересно, что же использует этот порт …
Ага, вот наш виновник! Теперь мы можем остановить эту программу если не хотим чтобы она была запущена и это освободит наш порт. Как программа fuser
нашла кто использует запрашиваемый порт? Именно! Это снова файловая система /proc
. По сути, она объединяет две вещи, которые мы уже изучили ранее: обход списка процессов и чтение активных подключений из /proc/net/tcp
. Нам нужен только один дополнительный шаг: найти способ ассоциировать информацию по открытым портам с PID. Если посмотреть данные о TCP, которые мы можем получить из /proc/net/tcp
, то PID там нет. Но мы можем использовать номер inode (иноды).
“Индексный дескриптор — это структура данных в традиционных для ОС UNIX файловых системах (ФС). В этой структуре хранится метаинформация о стандартных файлах, каталогах или других объектах файловой системы, кроме непосредственно данных и имени.” – Википедия
Как мы можем использовать иноду для поиска совпадающего процесса? Если мы посмотрим в каталог fd
процесса, который, как мы знаем имеет открытый порт, то найдем строку, наподобие этой:
Число между квадратными скобками это номер иноды. Теперь, все что нам нужно, это проитерировать все файлы и мы найдем совпадающий процесс.
Вот один из способов сделать это:
Пример вывода:
Помните, что запускать код, приведенный выше нужно от суперпользователя (root) или от пользователя - владельца процесса. В обратном случае вы не сможете читать информацию о процессе из /proc
.
Заключение
В этой заметке вы узнали, что Linux предоставляет много данных с помощью виртуальной файловой системы /proc
. Также вы научились воссоздавать популярные Linux утилиты такие как ps
, netstat
и fuser
с использованием данных, полученных из /proc
.