Как запустить Traceroute в Linux
Traceroute — это инструмент в Linux, позволяющий исследовать маршруты сетевых пакетов. Это может помочь вам определить ограничивающий фактор перемещения сетевых пакетов. Traceroute также полезен для устранения проблем с медленными сетевыми подключениями. В этом руководстве показано, как запустить traceroute в Linux.
О трассировке
Traceroute отправляет пакеты данных на целевой компьютер, сервер или веб-сайт и записывает любые промежуточные шаги, через которые проходят пакеты. Результатом команды traceroute будут IP-адреса и доменные имена, через которые проходят пакеты. Эти записи также показывают, сколько времени требуется, чтобы пакеты достигли каждого пункта назначения. Это может объяснить, почему некоторые веб-сайты загружаются дольше, чем другие, поскольку количество переходов трафика может варьироваться.
Traceroute также полезен для отображения локальных сетей. Понимание топологии и подключений локальной сети можно найти при запуске инструмента.
Обратите внимание, что при использовании traceroute некоторые устройства могут плохо взаимодействовать. Это может быть связано с ошибками маршрутизаторов, ограничивающими скорость сообщениями ICMP интернет-провайдерами, устройствами, не настроенными для отправки пакетов ICMP (для предотвращения распределенных DoS-атак) и т.д. Некоторые сети также настроены на блокировку запросов трассировки.
Установка traceroute
Traceroute — мощный инструмент, доступный для всех дистрибутивов Linux. Ниже приводится краткий список команд для установки traceroute в различных дистрибутивах.
Для Debian/Ubuntu и производных:
Для Fedora и производных:
Для openSUSE, SUSE Linux и производных:
Для Arch Linux и производных:
Использование traceroute
В следующих разделах показано, как использовать traceroute в вашей системе Linux.
Основное использование
Основной метод использования traceroute довольно прост. Все, что требуется traceroute, — это пункт назначения для выполнения зондирования. Назначением может быть домен или IP-адрес.
Если сеть настроена на блокировку сигнала traceroute, то этот зонд будет отмечен звездочками.
IPv4 или IPv6
По умолчанию traceroute будет использовать Интернет-протокол по умолчанию, на который настроена ваша система. Чтобы вручную установить версию IP, выполните описанную ниже процедуру.
Тестирование портов
Скрытие имен устройств
Предел тайм-аута Traceroute
Методы исследования
Установка максимального количества прыжков
По умолчанию traceroute отслеживает 30 переходов. Traceroute предлагает возможность вручную установить количество отслеживаемых переходов.
Указание интерфейса
Определение количества запросов для прыжка
Маршрутизация пакетов через шлюз
Страница справки Traceroute
Вышеупомянутые демонстрации — это лишь некоторые из распространенных способов использования traceroute, и вы можете использовать еще больше функций. Чтобы получить быструю помощь, откройте страницу справки traceroute с помощью следующей команды:
Чтобы получить более полное и подробное руководство по всем доступным параметрам traceroute, посетите страницу руководства с помощью следующей команды:
Заключение
Traceroute — это мощный инструмент, используемый для диагностики сети, и он поддерживает множество опций. Освоение traceroute может потребовать времени и практики. При использовании этого инструмента вы часто будете использовать методы, описанные в этой статье.
А ранее мы писали об использовании аналогичной команды tracert в Windows.
Как использовать трассировку, чтобы узнать о проблемах сети в Linux
Главное меню » Операционная система Linux » Как использовать трассировку, чтобы узнать о проблемах сети в Linux
Если есть проблема при подключении к IP/веб-сайту, трассировка может показать нам, где проблема. Это дает список всех маршрутизацию всех пакетов между вашим компьютером и веб – сервером. Это поможет вам убедиться, что маршрутизация по сетям идет правильно и быстро определить, нужно ли обратиться к команде поддержки.
Как работает Traceroute
При подключении к веб-сайту, трафик должен пройти через несколько посредников до достижения веб-сайта. Он проходит через локальный маршрутизатор, маршрутизаторы провайдера, маршруты большие сети до конечного пункта назначения.
Этот инструмент показывает вам путь, по которому трафик, необходимый для достижения веб-сайта. Он также отображает каждую задержку, что происходит на каждой остановке. Если есть проблемы, достигающие сайт, при том что определенный веб-сайт работает нормально, это может быть возможно существует проблема на пути между компьютером и серверами веб-сайта. Этот инструмент покажет вам, где эта проблема. Поскольку запросы Traceroute зависит от ответов на ICMP-запросы, некоторые пересылки на маршруте могут упасть в пользу более высокого приоритета сетевого трафика.
Как использовать Traceroute
Трассировка может быть запущена из окна терминала или из командной строки. Выполните команду трассировки с адресом веб-сайта. Например, если вы хотите запустить трассировку на Andreyex, вы бы выполнить команду:
Если вы используете трассировку для другого веб-сайта, размещенного в другом регионе мира, вы можете увидеть, как пути отличаются.
Первый “hops” так же, когда трафик достигает вашего поставщика услуг Интернета, а затем пакеты идут по другим сетям.
Понимание выводы
Первая линия показывает ваш домашний маршрутизатор (если у вас есть маршрутизатор), следующие строки представляет ваш провайдер, и далее вниз каждой строки представляет собой маршрутизатор, и так далее.
Формат каждой строки выглядит следующим образом:
Вот что означает каждое поле:
С трассировкой, вы можете получить представление о том, какие сервера стоят на вашем пути к определенному домену или какой IP-адрес вызывает проблемы.
Теперь вы должны быть в состоянии использовать команду tracert и понять его вывод.
Если вы нашли ошибку, пожалуйста, выделите фрагмент текста и нажмите Ctrl+Enter.
Команда traceroute Linux
Не всегда сеть работает так, как от нее требуется, иногда определенный компьютер в вашей локальной сети компании, или удаленный может не отвечать. Казалось бы, все работает, все подключено, но похоже на каком-то из узлов, на пути от вашего компьютера, до нужного случается ошибка.
Утилита ping позволяет только определить наличие проблемы, что узел не отвечает, но как узнать где обрывается соединение? Для этого применяется утилита traceroure. В этой небольшой инструкции мы рассмотрим как пользоваться traceroute linux, как понимать ее вывод и определить где же все-таки проблема. Но сначала рассмотрим, как работает traceroute.
Как работает traceroute?
Вы, наверное, уже знаете, что вся информация в сети передается в виде пакетов. Поток данных разбивается специальным программным обеспечением на небольшие пакеты и передается через сеть интернет на целевой узел, а там собирается обратно.
Каждый пакет проходит на своем пути определенное количество узлов, пока достигнет своей цели. Причем, каждый пакет имеет свое время жизни. Это количество узлов, которые может пройти пакет перед тем, как он будет уничтожен. Этот параметр записывается в заголовке TTL, каждый маршрутизатор, через который будет проходить пакет уменьшает его на единицу. При TTL=0 пакет уничтожается, а отправителю отсылается сообщение Time Exceeded.
Команда traceroute linux использует UDP пакеты. Она отправляет пакет с TTL=1 и смотрит адрес ответившего узла, дальше TTL=2, TTL=3 и так пока не достигнет цели. Каждый раз отправляется по три пакета и для каждого из них измеряется время прохождения. Пакет отправляется на случайный порт, который, скорее всего, не занят. Когда утилита traceroute получает сообщение от целевого узла о том, что порт недоступен трассировка считается завершенной.
Утилита Traceroute
Перед тем как перейти к примерам работы с утилитой давайте рассмотрим ее синтаксис и основные опции. Синтаксис вызова очень прост:
$ traceroute опции адрес_узла
В качестве адреса может использоваться ip адрес или доменное имя. Рассмотрим основные опции:
Это не все опции утилиты, но все основные, которыми вы будете пользоваться. Дальше перейдем практике того, как выполняется трассировка сети Linux.
Примеры трассировки сети в Linux
Например, выполним трассировку до сервера losst.ru:
sudo traceroute losst.ru
Как видите, пакет прошел через 6 узлов перед тем, как дойти до цели. На каждый узел отправлялось по три пакета и для каждого из них было засечено время прохождения. И если на одном из узлов возникнет проблема, теперь вы будете знать на каком.
У вас, наверное, возник вопрос, почему время прохождения для некоторых узлов такое долгое? Ведь если выполнить ping, то общее время будет намного меньше. Дело в том, что время засекается для пути пакета туда и обратно. От запроса до ответа. Это раз, но еще нужно учитывать что маршрутизаторы дают высший приоритет для приходящих пакетов, когда для сервисных задержки могут быть более длинными.
Еще, вместо одного узла вы можете видеть звездочки traceroute. Это еще не значит, что он не работает. Это означает что всего лишь он не захотел нам отвечать. Давайте проверим еще что-нибудь, например, публичный DNS google:
sudo traceroute 8.8.8.8
Здесь уже больше узлов, и такая же ситуация со звездочками. Если бы на пути к серверу возникла ошибка, мы бы это увидели. Например, узел 195.153.14.1 нам не ответил и мы смогли отследить запрос только до 212.162.26.169.
sudo traceroute 195.153.14.1
sudo traceroute history.pl
Но трассировка может использоваться не только для обнаружения обрыва в цепочке маршрутизаторов. У нее еще есть достаточно интересное применение по исследованию сети. Например, вы можете попытаться определить использование подсетей провайдером. Отправим три запроса на разные адреса:
sudo traceroute losst.ru
$ sudo traceroute history.pl
$ sudo traceroute habrahabr.ru
Затем сравните выводы этих команд. Вы увидите, что начальные IP адреса одинаковые. Мы можем сделать вывод, что наш роутер 192.168.1.1 подключен к локальной сети провайдера 195.5.8.0/24, которая, в свою очередь, подключена к сети 10.50.50.0/24 откуда уже получает доступ к внешней сети.
Выводы
В этой статье мы рассмотрели как работает команда traceroute linux, а также как выполняется трассировка сети linux. Эти функции больше нужны системным администраторам, но и обычным пользователям тоже иногда могут пригодиться.
Команда traceroute в системе Linux
Часто какой-нибудь сегмент сети не работает должным образом. Как ни странно, при проверке часто обнаруживается, что используемое оборудование подключено и исправно. Трудно определить, что не работает, на каком участке проблема. На это есть своё объяснение. Это означает, что одно из устройств в локальной сети попросту не отвечает, что приводит к потере некоторых данных. Необходимо разобраться, какой из узлов дал сбой. Это легко проверить при помощи специальной утилиты под названием traceroute в Линукс.
В данной статье рассматривается использование проверенного инструмента только для компьютеров Linux. В других системах эти инструкции не работают.
Принцип работы трассировки
Данные в сети передаются в виде пакетов. Об этом знает даже новичок. Поток информации нуждается в разбивке, что обеспечивают специальные программы, установленные на компьютере. Далее эти пакеты отправляются на целевой узел через Интернет, после чего поток информации заново собирается.
Каждая «порция» данных имеет ограниченный срок жизни и переходит от узла к узлу, достигая конечной цели. По умолчанию утилита traceroute использует пакеты формата UDP, но данный параметр поддается коррективам. Вскоре вы сами в этом убедитесь.
команда traceroute не найдена
Обычно по умолчание утилита traceroute не входит в комплект дистрибутивов Линукс и поэтому при использовании трассировки можно получить ошибку «команда не найдена», в английском варианте «command not found».
Установка в Убунту, Debian:
# apt update
# apt install traceroute
# yum install traceroute
# dnt install traceroute
Синтаксис
Рассмотрим синтаксис команды.
В той части команды, где будет указан адрес узла, необходимо прописать доменное имя или IP-адрес.
Дополнительные опции
Вышеперечисленные ключи не являются обязательными для использования traceroute в командной строке устройства Линукс. Вы всегда можете запустить утилиту без добавления вспомогательных опций.
Примеры трассировки в Linux
Рассмотрим на примере выполнение трассировки сети до определенного сервера. Он будет указан в завершении:
Как видно из скриншота, пакет дошел до сайта всего за два хоста
Система отправляла по 3 пакета на каждый из этих узлов, засекая при этом точное время их прохождения. Имея подобную информацию на руках, очень просто понять, на каком узле возникла проблема, если сеть дала сбой.
Следует учитывать тот факт, что сервисная задержка может отнять немало времени. Это связано с приоритетностью маршрутизатора. Приходящие пакеты всегда находятся в фаворе.
Если в появившемся окне вместо узла указаны звёздочки утилиты, не стоит делать поспешных выводов о его поломке. Скорее всего, узел просто не ответил на этот раз.
Для начала пробуем без изменений:
Если не получается, измените формат пакетов:
Обрыв цепочки – не единственное, что может выявить трассировка сети Linux. Её также можно применить для исследования сети. К примеру, пользователю нужно выяснить, какие подсети используются поставщиком Интернет-услуг. Для этого необходимо отправить 3 запроса с указанием разных адресов. Вот так это выглядит на практике:
Чтобы разобраться с полученными данными и сделать правильное умозаключение, следует провести сравнение 3 выводов заданных команд. Вы увидите, к какой локальной сети подключен ваш маршрутизатор, и какие сети использует провайдер.
Подводя итог, следует резюмировать основные функции команды traceroute:
Заключение
Утилита treaceroute – весьма популярный и надежный инструмент для проверки обрыва цепочки, используемый не только системными администраторами, но и обычными пользователями дистрибутива Linux. Эта команда может пригодиться при различных неисправностях. Её рекомендуется использовать исключительно для ручной локализации проблем. Использование traceroute во время стандартных операций и автоматических сценариев может оказать мощную нагрузку на сеть, что не является целесообразным решением.
Полнофункциональная динамическая трассировка в Linux с использованием eBPF и bpftrace
«В режиме трассировки программист видит последовательность выполнения команд и значения переменных на данном шаге выполнения программы, что позволяет легче обнаруживать ошибки» — сообщает нам Википедия. Сами будучи поклонниками Linux, мы регулярно сталкиваемся с вопросом, какими именно инструментами её лучше осуществлять. И хотим поделиться переводом статьи программиста Хонгли Лая, который рекомендует bpftrace. Забегая вперёд, скажу, что заканчивается статья лаконично: «bpftrace — это будущее». Так чем же он так впечатлил коллегу Лая? Развёрнутый ответ под катом.
В Linux есть два основных инструмента трассировки:
strace позволяет вам увидеть, какие совершаются системные вызовы;
ltrace позволяет увидеть, какие вызываются динамические библиотеки.
Несмотря на свою полезность, эти инструменты ограничены. А если вам нужно выяснить, что происходит внутри системного или библиотечного вызова? А если вам нужно не просто составить список вызовов, но и, например, собрать статистику по определённому поведению? А если вам нужно трассировать несколько процессов и сопоставить данные из нескольких источников?
В 2019 году мы, наконец, получили достойный ответ на эти вопросы на Linux: bpftrace, основанный на технологии eBPF. Bpftrace позволяет писать небольшие программы, которые выполняются каждый раз, когда происходит событие.
В этой статье я опишу, как установить bpftrace и научу его базовому применению. А также сделаю обзор того, как выглядит трассировочная экосистема (например, «что такое eBPF?») и как она развивалась в то, что мы имеем сегодня.
Что такое трассировка?
Как уже было сказано ранее, bpftrace позволяет писать небольшие программы, которые выполняются каждый раз, когда происходит событие.
Что такое событие? Это может быть системный вызов, вызов функции или даже что-то, происходящие внутри таких запросов. Это также может быть таймер или аппаратное событие, например «50 мс прошло с последнего такого же события», «произошёл отказ страницы», «произошло переключение контекста» или «произошёл cashe-miss процессора».
Что можно сделать в ответ на событие? Вы можете что-нибудь залогировать, собрать статистические данные и выполнить произвольные команды оболочки. У вас будет доступ к различной контекстной информации, такой как текущий PID, трассировка стека, время, аргументы вызовов, возвращаемые значения, и т.д.
В каких случаях использовать? Во многих. Вы можете разобраться в том, почему приложение медленно работает, собрав список наиболее медленных вызовов. Вы можете определить, имеются ли в приложении утечки памяти и если да, то откуда. Я использую его, чтобы разбираться с тем, почему Ruby использует так много памяти.
Большим плюсом bpftrace является то, что вам нет нужды перекомпилировать приложения. Нет необходимости руками прописывать в исходниках исследуемого приложения вызовы print или любой другой отладочный код. Нет даже необходимости перезапуска приложений. И всё это с очень низкими накладными расходами. Это делает bpftrace особенно полезным для отладки систем прямо на проде или в иной ситуации, когда есть сложности с перекомпиляцией.
DTrace: отец трассировки
В течение долгого времени лучшим инструментом для трассировки был DTrace, полновесный фреймворк для динамической трассировки, изначально разработанный Sun Microsystems (создателями Java). Как и bpftrace, DTrace позволяет писать небольшие программы, которые выполняются в ответ на события. На самом деле, многие ключевые элементы экосистемы в значительной степени разработаны Бренданом Греггом, известным экспертом по DTrace, который сейчас работает в Netflix. Что объясняет сходство между DTrace и bpftrace.
Solaris DTrace introduction (2009) by S. Tripathi, Sun Microsystems
В какой-то момент Sun открыли исходники DTrace. Сегодня DTrace доступен на Solaris, FreeBSD и macOS (хотя версия для macOS в целом неработоспособна, поскольку Защита Системной Целостности, SIP, сломала многие принципы, на которых работает DTrace).
Да, вы правильно заметили… Linux в этом списке отсутствует. Это не инженерная проблема, это проблема лицензирования. DTrace был открыт под лицензией CDDL вместо GPL. Порт DTrace на Linux был доступен с 2011 года, но он никогда не поддерживался основными разработчиками Linux. В начале 2018 года Oracle переоткрыли DTrace под GPL, но к тому моменту было уже слишком поздно.
Экосистема трассировки в Linux
Без сомнения, возможность трассировки очень полезна, и сообщество Linux стремилось разработать свои собственные решения на эту тему. Но, в отличие от Solaris, Linux не регулируется одним конкретным вендором, в связи с чем не возникало целенаправленных усилий разработать полнофункциональную замену DTrace. Экосистема трассировки в Linux развивалась медленно и естественно, решая проблемы по мере их возникновения. И только недавно эта экосистема выросла достаточно, чтобы серьёзно конкурировать с DTrace.
Из-за естественного роста эта экосистема может показаться немного хаотичной, состоящей из множества различных компонентов. К счастью, Джулия Эванс написала обзор этой экосистемы (внимание, дата публикации — 2017 год, до появления bpftrace).
Экосистема трассировки Linux, описанная Джулией Эванс
Не все элементы одинаково важны. Позвольте мне кратко резюмировать, какие элементы я считаю наиболее важными.
Данные о событиях могут поступать как из ядра, так и из пространства пользователя (приложений и библиотек). Некоторые из них доступны автоматически, без дополнительных усилий разработчиков, остальные же требуют ручного объявления.
Обзор самых важных источников трассируемых событий в Linux
Со стороны ядра существует kprobes (от «kernel probes», «датчик ядра», прим. пер.) — механизм, позволяющий трассировать любой вызов функции внутри ядра. С его помощью вы можете трассировать не только сами системные вызовы, но и то, что происходит внутри них (потому что точки входа системных вызовов вызывают другие внутренние функции). Вы также можете использовать kprobes для трассировки событий ядра, не являющихся системными вызовами, например, «буферизированные данные записываются на диск», «TCP-пакет посылается по сети» или «в данный момент происходит переключение контекста».
Точки трассировки (tracepoints) ядра позволяют трассировать нестандартные события, определённые разработчиками ядра. Эти события находятся не на уровне вызовов функций. Для создания таких точек разработчики ядра вручную размещают макрос TRACE_EVENT в коде ядра.
У обоих источников есть и плюсы и минусы. Kprobes работает «автоматически», т.к. не требует от разработчиков ядра ручной разметки кода. Но события kprobe могут произвольно меняться от одной версии ядра к другой, потому что функции постоянно изменяются — добавляются, удаляются, переименовываются.
Точки трассировки ядра, как правило, более стабильны с течением времени и могут предоставлять полезную контекстную информацию, которая может быть недоступна в случае использования kprobes. Используя kprobes, можно получить доступ к аргументам вызовов функций. Но с помощью точек трассировки можно получить любую информацию, которую разработчик ядра решит вручную описать.
В пространстве пользователя существует аналог kprobes — uprobes. Он предназначен для трассировки вызовов функций в пространстве пользователя.
Датчики USDT («Статически Определённые Трассировки Пользовательского Пространства») — это аналог точек трассировки ядра в пространстве пользователя. Разработчикам приложений необходимо вручную добавлять датчики USDT в свой код.
Интересный факт: DTrace в течение долгого времени предоставлял C API для определения собственного аналога USDT датчиков (с помощью макроса DTRACE_PROBE). Разработчики экосистем трассировки в Linux решили оставить исходный код совместимым с этим API, так что любые макросы DTRACE_PROBE автоматически преобразуются в USDT датчики!
Поэтому, в теории, strace может быть реализован с помощью kprobes, а ltrace — с помощью uprobes. Я не уверен, практикуется ли такое уже или нет.
Интерфейсы — это приложения, позволяющие пользователям с легкостью использовать источники событий.
Давайте рассмотрим, как работают источники событий. Рабочий процесс выглядит следующим образом:
Существуют интерфейсы на любой вкус и цвет. В области интерфейсов на основе eBPF есть низкоуровневые, требующие глубокого понимания того, как взаимодействовать с источниками событий и как работает байт-код eBPF. А есть и высокоуровневые и простые в эксплуатации, хотя за время своего существования они не демонстрировали большой гибкости.
Вот почему bpftrace – новейший интерфейс – это мой любимый. Он легкий в использовании и гибкий, как DTrace. Но он довольно новый и требует шлифовки.
eBPF — это новая звезда трассировки в Linux, на которой базируется bpftrace. Когда вы трассируете событие, вы хотите чтобы «что-то» случилось в ядре. Как гибким способом определить что есть это «что-то»? Конечно, с помощью языка программирования (или с помощью машинного кода).
eBPF (расширенной версии Пакетного Фильтра Беркли). Это высокопроизводительная виртуальная машина, которая работает в ядре и имеет следующие свойства/ограничения:
Темные дни до eBPF
До появления eBPF варианты решения были, мягко говоря, неуклюжими. SystemTap — что-то вроде «наиболее серьезного» предшественника bpftrace в семействе Linux. Cкрипты SystemTap транслируются в язык C и загружаются в ядро в виде модулей. Полученный модуль ядра затем загружается.
Этот подход был очень хрупким и плохо поддерживался вне Red Hat Enterprise Linux. У меня он никогда хорошо не работал на Ubuntu, которая имела тенденцию ломать SystemTap на каждом обновлении ядра по причине изменения структуры данных ядра. Говорят также, что в первые дни своего существования SystemTap легко приводил к kernel panic.
Установка bpftrace
Пришло время засучить рукава! В этом руководстве мы рассмотрим установку bpftrace на Ubuntu 18.04. Более новые версии дистрибутива использовать нежелательно, т.к. при установке нам понадобятся пакеты, которые пока для них не собраны.
Для начала установим Clang 5.0, lbclang 5.0 и LLVM 5.0, включая все заголовочные файлы. Мы будем использовать пакеты, предоставляемые llvm.org, потому что те, что есть в репозиториях Ubuntu, проблемные.
И, наконец, установите libbfcc-dev из апстрима, а не из репозитория Ubuntu. В пакете, что есть в Ubuntu, отсутствуют заголовочные файлы. И эта проблема не была решена даже в 18.10.
Основная установка bpftrace
Пришло время установить сам bpftrace из исходников! Давайте склонируем его, соберём и установим в /usr/local:
И готово! Исполняемый файл будет установлен в /usr/local/bin/bpftrace. Вы можете изменить целевое расположение, используя аргумент для cmake, который по умолчанию выглядит вот так:
Давайте запустим несколько однострочников bpftrace, чтобы понять наши возможности. Эти я взял из руководства Брендана Грегга, в котором есть подробное описание каждого из них.
# 1. Выводим список датчиков
# 2. Приветственное слово
# 4. Количество системных вызовов на процесс
# 5. Распределение вызовов read() по количеству байт
# 6. Динамическая трассировка содержимого read()
# 7. Время, затраченное на вызовы read()
# 8. Подсчёт событий уровня процесса
# 9. Профайлинг рабочих стеков ядра
# 10. Трассировка планировщика
# 11. Трассировка блокирующего ввода/вывода
Синтаксис скриптов и пример тайминга ввода/вывода
Строка, передаваемая через ключ ‘-e’ — это содержимое скрипта bpftrace. Синтаксис в данном случае — это, условно, набор конструкций:
Давайте разберём седьмой пример, про тайминги операций чтения файловой системы:
Трассируем событие от механизма kprobe, т. е. отслеживаем начало функции ядра.
Функция ядра для трассировки — vfs_read, эта функция вызывается, когда ядро производит операцию чтения с файловой системы (VFS от «Virtual FileSystem», абстракции файловой системы внутри ядра).
Когда начинает выполняться vfs_read (т.е. до того, как функция выполнила какую-либо полезную работу), запускается программа bpftrace. Она сохраняет текущую метку времени (в наносекундах) в глобальный ассоциативный массив, именуемый stаrt. Ключом является tid, ссылка на текущий идентификатор потока (thread id).
1. Трассируем событие от механизма kretprobe, который похож на kprobe, за исключением того, что он вызывается, когда функция возвращает результат своего выполнения.
2. Функция ядра для трассировки — vfs_read.
3. Это опциональный фильтр. Он проверяет, было ли ранее записано время старта. Без этого фильтра программа может быть запущена во время чтения и поймать только конец, в результате чего получить рассчётное время nsecs — 0, вместо nsecs — start.
nsecs — stаrt[tid] вычисляет, сколько времени прошло с начала работы функции vfs_read.
@ns[comm] = hist(. ) добавляет указанные данные в двумерную гистограмму, хранящуюся в @ns. Ключ comm ссылается на имя текущего приложения. Так что у нас будет покомандная гистограмма.
delete(. ) удаляет время начала из ассоциативного массива, потому что оно нам больше не требуется.
Это окончательный вывод. Обратите внимание, что все гистограммы выводятся автоматически. Явное использование команды «напечатать гистограмму» не требуется. @ns — это не специальная переменная, так что гистограмма выводится не из-за него.
Пример датчика USDT
Давайте возьмём этот код на Си и сохраним его в файле tracetest.c:
Эта программа выполняется бесконечно, вызывая myclock() раз в секунду. myclock() запрашивает текущее время и возвращает количество секунд с начала эпохи.
Вызов DTRACE_PROBE1 здесь определяет статическую точку трассировки USDT.
Мы поручаем bpftrace вывести PID и «time is [число]» всякий раз, когда достигается testprobe:
Bpftrace продолжает работать, пока мы нажмём Ctrl-С. Поэтому откроем новый терминал и запустим tracetest там:
# В новом терминале
./tracetest
Вернитесь к первому терминалу с bpftrace, там вы должны увидеть что-то вроде:
Пример выделения области памяти с помощью glibc ptmalloc
Я использую bpftrace, чтобы разбираться с тем, почему Ruby использует так много памяти. И в части моего исследования мне требуется понимание того, как аллокатор памяти glibc использует области памяти.
В целях оптимизации многоядерной производительности, аллокатор памяти glibc выделяет несколько «областей» из ОС. Когда приложение запрашивает выделение памяти, аллокатор выбирает область, которая не используется, и помечает часть этой области как «использующуюся». Так как потоки используют различные области, количество блокировок уменьшается, что приводит к улучшению многопоточной производительности.
Но такой подход генерирует много мусора, и похоже, что такое высокое потребление памяти в Ruby именно из-за него. Для того чтобы лучше понять природу этого мусора, я задался вопросом: что вообще значит «выбрать область, которая не используется»? Это может означать одно из:
Вот функция аллокатора памяти glibc, который создает новую область. Но вызывать ее можно только после проверки лимита.
Можно ли использовать uprobes для трассирования функции _int_new_arena? К сожалению, нет. По какой-то причине этот символ не доступен в glibc Ubuntu 18.04. Даже после установки отладочных символов.
К счастью, в этой функции есть USDT-датчик. LIBC_PROBE — это макрос-псевдоним для STAP_PROBE.
Имя провайдера — libc.
Имя датчика — memory_arena_new.
Цифра 2 означает, что есть 2 дополнительных аргумента, заданных разработчиком.
arena — это адрес области, которая была выделена из ОС, а size — её размер.
Прежде чем мы сможем использовать этот датчик, нам нужно обойти проблему 328. Нам нужно создать символическую ссылку с glibc куда-нибудь с именем именно libc, потому что bpftrace ожидает, что имя библиотеки (которое в противном случае было бы libc-2.27.so) будет идентично имени провайдера (libc).
Теперь мы поручаем bpftrace прицепиться к USDT датчику memory_arena_new, именем поставщика которого является libc:
В другом терминале мы запустим Ruby, который создаст три ничего не делающих потока и через секунду завершится. Из-за глобальной блокировки интерпретатора Ruby malloc() не должен вызываться параллельно разными потоками.
Вернувшись к терминалу с bpftrace, мы увидим:
Вот ответ на наш вопрос! Каждый раз при создании нового потока в Ruby glibc выделяет новую область безотносительно конкурентности.
Какие доступны точки трассировки? Что я должен трассировать?
Вы можете перечислить всё оборудование, таймеры, kprobe и статические точки трассировки ядра, выполнив команду:
Вы можете перечислить все точки трассировки uprobe (функциональные символы) приложения или библиотеки, выполнив:
Вы можете перечислить все точки трассировки USDT приложения или библиотеки, выполнив следующую команду:
Касательно того, какие точки трассировки использовать: тут не помешало бы понимание исходников того, что вы собираетесь трассировать. Я рекомендую вам изучать исходный код.
Совет: структурный формат точек трассировки в ядре
Вот полезная заметка по точкам трассировки ядра. Вы можете проверить, какие доступны поля аргументов, прочитав файл /sys/kernel/debug/tracing/events!
Например, предположим, что вы хотите трассировать вызовы madvise(. MADV_DONTNEED):
— скажет нам, что мы можем использовать tracepoint:syscalls:sys_enter_madvise.
— даст нам следующую информацию:
Подпись madvise согласно мануалу: (void *addr, size_t length, int advice). Последние три поля этой структуры соответствуют этим параметрам!
Каково значение MADV_DONTNEED? Судя по grep MADV_DONTNEED /usr/include, оно равняется 4:
Так что наша команда bpftrace становится:
Заключение
Bpftrace прекрасен! Bpftrace — это будущее!
Если вы хотите узнать о нём побольше, то я рекомендую ознакомиться с его руководством, а также с первым постом 2019 года в блоге Брендана Грегга.