Библиотека — FreeBSD — мониторинг и отладка: от top до DTrace [X]
Шифр
freebsd-monitoring-debugging
Разделы
freebsd tooling
Сверено
2 сентября — в этот день утверждения статьи сверялись с первоисточниками, а не правился текст
Объём
21 255 знаков · 46 разделов · чтения около 20 минут

FreeBSD — мониторинг и отладка: от top до DTrace


Обзор

FreeBSD включает в base system набор диагностических инструментов, покрывающий всё: от беглого взгляда на загрузку (top, vmstat) до глубокого анализа поведения ядра на лету (DTrace). Многое из того, что в Linux требует установки сторонних пакетов (sysstat, iotop, bpftrace), во FreeBSD доступно из коробки.

Статья организована по уровням погружения: быстрая диагностика → детальный анализ по подсистемам (CPU, RAM, диск, сеть) → логи → DTrace для глубоких расследований. Каждый уровень — ответ на вопрос "что происходит с системой?" с нарастающей детализацией.

Быстрая диагностика: первые 60 секунд

Когда система "тормозит" или ведёт себя странно, начинать с общей картины.

top

top                                # интерактивный монитор процессов
top -S                             # включить системные (ядерные) процессы
top -o res                         # сортировать по resident memory
top -P                             # показать загрузку по отдельным CPU

top во FreeBSD — base system, не требует установки. Показывает load average, CPU states (user/nice/system/interrupt/idle), память (Active/Inact/Wired/Buf/Free), swap, и список процессов.

Ключевые CPU states: interrupt — время в обработчиках прерываний (высокое значение → проблема с драйвером или hardware); system — ядерное время (высокое → много системных вызовов, возможно I/O bound). idle — свободный CPU. Если idle близок к нулю — система перегружена.

Интерактивные команды: m — переключиться между режимами отображения cpu и io (второй показывает per-process I/O; то же самое даёт ключ -m io), P — CPU per core, S — toggle system processes, o — сменить сортировку, s — изменить интервал обновления.

vmstat

vmstat 1                           # обновление каждую секунду
procs  memory       page           disks     faults         cpu
r b w  avm   fre   flt  re  pi  po  fr  sr da0  in   sy   cs us sy id
2 0 0 1.2G  340M   245   0   0   0   0   0   3  412 2841 1205  4  2 94

r — процессы в очереди на исполнение (run queue). Если r стабильно больше числа CPU — процессор перегружен. b — процессы, заблокированные на I/O. w — процессы в swap (swapped out). fre — свободная память. pi/po — страницы swap in/out (ненулевые = система свопит). cs — context switches. in — interrupts. us/sy/id — user/system/idle CPU.

Первая строка vmstat — среднее с момента загрузки, последующие — реальное время. Игнорировать первую строку.

systat

systat(1) — curses-based монитор из base system с множеством режимов:

systat -vmstat 2                   # общая статистика, обновление 2 сек
systat -iostat 2                   # дисковый I/O
systat -ifstat 2                   # сетевые интерфейсы
systat -netstat 2                  # сетевые соединения
systat -pigs 2                     # процессы-"свиньи" по CPU
systat -zarc 2                     # ZFS ARC статистика
systat -ip 2                       # IP-трафик
systat -tcp 2                      # TCP-статистика

Навигация: vi-стиль. :vmstat — переключить режим. :q — выход. Не q, а именно :q.

systat -zarc особенно полезен для ZFS-систем: показывает hit rate ARC-кэша, размеры, demand vs prefetch. Если ARC hit rate ниже 80-90% — стоит увеличить vfs.zfs.arc.max.

CPU: детальный анализ

Кто ест процессор

top -o cpu                         # сортировка по CPU в top
ps auxr | head                     # топ процессов по CPU (однократный срез)

CPU profiling встроенными средствами

# pmcstat — hardware performance counters (base system)
kldload hwpmc                      # драйвер собран модулем, не в GENERIC
pmcstat -S instructions -T         # top-подобный профиль по инструкциям
pmcstat -S unhalted-cycles -O profile.pmc sleep 10   # профиль за 10 секунд

pmcstat(8) использует аппаратные счётчики процессора (PMC — Performance Monitoring Counters). В GENERIC есть только options HWPMC_HOOKS, сам драйвер hwpmc(4) подгружается модулем (sysrc kld_list+=hwpmc, чтобы это переживало перезагрузку). Доступность событий зависит от CPU; машинно-независимых псевдонимов всего восемь — branches, branch-mispredicts, cycles, dc-misses, ic-misses, instructions, interrupts, unhalted-cycles, всё остальное задаётся именами конкретной микроархитектуры. Строчные -s/-p — счётчики, прописные -S/-P — сэмплирование (system-wide и process-mode соответственно). pmc(3) перечисляет доступные события.

Средняя загрузка и scheduling

sysctl vm.loadavg                  # load average (1, 5, 15 мин)
sysctl kern.cp_time                # накопленное CPU time по состояниям

Load average во FreeBSD (как и в Linux) включает и процессы в run queue, и процессы, ожидающие I/O. Высокий LA при низком CPU usage → I/O bottleneck, а не CPU.

Память: кто и сколько

Общая картина

top                                # раздел Mem: Active, Inact, Wired, Buf, Free
vmstat -s                          # подробная статистика VM
sysctl hw.physmem                  # физическая память
sysctl hw.usermem                  # доступная пользователю
sysctl vm.stats.vm.v_free_count    # свободные страницы

Категории памяти FreeBSD: Active — активно используемые страницы; Inact — недавно использованные, кандидаты на вытеснение; Laundry — грязные неактивные страницы, которые нужно записать в swap или на файловую систему, прежде чем освободить (отдельная очередь PQ_LAUNDRY и свой поток-«прачечная»); Wired — запинены в RAM, не могут быть вытеснены (ядро, ZFS ARC); Buf — буферный кэш; Free — свободные.

Wired memory на ZFS-системе часто велика — это ARC. Если Free + Inactive → близко к нулю — система испытывает давление на память.

Swap

swapinfo -h                        # использование swap
pstat -s                           # подробнее

Ненулевой swap usage — не обязательно проблема. Неактивные страницы могут быть вытеснены в swap без влияния на производительность. Проблема — активный swapping: vmstat 1 покажет ненулевые pi/po (page in/out).

Кто потребляет память

top -o res                         # сортировка по resident memory
ps auxm | head                     # топ по потреблению памяти

Для ZFS:

sysctl kstat.zfs.misc.arcstats.size            # текущий ARC
sysctl vfs.zfs.arc.max                         # максимум ARC
sysctl kstat.zfs.misc.arcstats.hits            # попадания в кэш
sysctl kstat.zfs.misc.arcstats.misses          # промахи
systat -zarc 2                                  # интерактивно

Диск: I/O и файловые системы

iostat

iostat -x 2                        # расширенная статистика, 2 сек
iostat -d -w 2                     # только диски
device     r/s    w/s   kr/s    kw/s  ms/r  ms/w  ms/o  ms/t qlen  %b
da0       12.3    8.7  245.0   156.0   0.8   1.2   0.0   0.9    1   2

ms/r, ms/w — средняя латентность чтения/записи в миллисекундах. Для SSD < 1ms нормально, для HDD — 5-15ms. %b — процент времени, когда диск занят. qlen — длина очереди.

gstat

gstat                              # GEOM-статистика в реальном времени
gstat -a                           # только провайдеры, занятые хотя бы на 0.1%

gstat(8) показывает I/O для каждого GEOM-провайдера (диски, партиции, ZFS vdev). Удобнее iostat для быстрой диагностики — интерактивный, обновляется непрерывно.

ZFS I/O

zpool iostat 2                     # I/O по пулам
zpool iostat -v 2                  # с разбивкой по vdev

Что читает/пишет файлы

fstat                              # открытые файлы всех процессов
fstat -p <PID>                     # конкретный процесс

Сеть: трафик, соединения, проблемы

netstat

netstat -i                         # статистика интерфейсов (ошибки, дропы)
netstat -s                         # статистика по протоколам (TCP retransmissions!)
netstat -an                        # все соединения
netstat -an -p tcp | grep ESTABLISHED | wc -l   # число активных TCP
netstat -m                         # mbuf статистика (буферы сетевого стека)

netstat -s | grep retransmit — ретрансмиссии TCP. Растущее число → потери пакетов, проблемы с сетью или перегрузка.

netstat -m — mbuf allocations. Если в строке "requests for mbufs denied (mbufs/clusters/mbuf+clusters)" числа ненулевые — не хватает сетевых буферов, нужно увеличить kern.ipc.nmbclusters в loader.conf.

sockstat

sockstat -l                        # слушающие сокеты (аналог ss -ln в Linux)
sockstat -4                        # только IPv4
sockstat -c                        # подключённые

tcpdump и pflog

tcpdump -i vtnet0 -n port 80      # трафик на порт 80
tcpdump -i pflog0 -n              # трафик, заблокированный/пропущенный PF
tcpdump -r /var/log/pflog          # прочитать сохранённый pflog

Пропускная способность в реальном времени

systat -ifstat 2                   # throughput по интерфейсам
netstat -I vtnet0 -w 1            # bytes in/out для интерфейса, 1 сек

Логирование

Ключевые лог-файлы

/var/log/messages          # общие системные сообщения
/var/log/auth.log          # аутентификация (SSH, su, doas)
/var/log/security          # security-события
/var/log/cron              # cron jobs
/var/log/daemon.log        # сообщения демонов (facility daemon)
/var/log/maillog           # почта
/var/log/debug.log         # debug-сообщения
/var/run/dmesg.boot        # dmesg при загрузке (сохраняется)

Оперативный анализ

tail -f /var/log/messages          # следить за логами в реальном времени
grep -i error /var/log/messages    # искать ошибки
dmesg | tail -30                   # последние сообщения ядра
dmesg -a                           # все сообщения ядра, включая verbose

syslogd

Конфигурация — /etc/syslog.conf. Описана в статье о безопасности (флаг -ss для закрытия сетевого сокета). Для отладки полезно временно увеличить verbosity:

# Добавить в /etc/syslog.conf для отладки конкретного facility
local0.*    /var/log/myapp.log

# Перечитать конфиг
service syslogd reload

newsyslog — ротация

newsyslog -nv                      # dry run: что было бы ротировано и почему
newsyslog -F                       # принудительно ротировать, не дожидаясь условий

Конфигурация /etc/newsyslog.conf описана в статье о безопасности.

Процессы и системные вызовы

ps — срез процессов

ps auxww                           # все процессы с полными командными строками
ps -axo pid,ppid,user,%cpu,%mem,vsz,rss,stat,command   # кастомный формат
ps -axd                            # дерево процессов (иерархия)

Столбец STAT: R — running, S — sleeping (interruptible), D — disk wait (uninterruptible), I — idle, Z — zombie, T — stopped. Процессы в D — ждут I/O, не могут быть убиты сигналом.

truss — трассировка системных вызовов

truss -p <PID>                     # присоединиться к работающему процессу
truss -f command                   # трассировка с отслеживанием дочерних процессов
truss -c command                   # подсчёт вызовов (summary)
truss -e command                   # показывать окружение, передаваемое в execve

truss(1) — FreeBSD-аналог strace из Linux. Входит в base system. Показывает каждый системный вызов процесса с аргументами и возвращаемыми значениями. Незаменим для диагностики "почему программа не запускается" или "что она пытается открыть".

procstat

procstat -f <PID>                  # открытые файловые дескрипторы
procstat -k <PID>                  # стек ядра (где заблокирован)
procstat -t <PID>                  # треды
procstat -s <PID>                  # сигналы
procstat -v <PID>                  # виртуальная память (mmap'ы)

procstat(1) — мощная утилита из base system для инспекции процессов. procstat -k особенно полезна: если процесс "висит", покажет, на каком системном вызове он заблокирован.

DTrace: динамическая трассировка

DTrace — фреймворк трассировки из Solaris, портированный в FreeBSD. Позволяет инструментировать работающее ядро и userland-программы на лету, без перезагрузки и без влияния на производительность (пока probe неактивен — overhead нулевой).

В GENERIC-ядре FreeBSD поддержка DTrace включена начиная с FreeBSD 9.2. Ядерный DTrace поддержан полностью, userland-DTrace в документации проекта до сих пор помечен как экспериментальный.

# Загрузить модули DTrace вручную; начиная с 10.0 dtrace(1) делает это сам
kldload dtraceall

# Установить DTrace Toolkit — коллекция готовых скриптов
pkg install dtrace-toolkit

Концепция: probe → predicate → action

DTrace-скрипт состоит из правил вида: при срабатывании probe (если predicate истинен) — выполнить action.

provider:module:function:name
/predicate/
{
    action;
}

Практические однострочники

# Кто делает системные вызовы? (топ процессов по числу syscall)
dtrace -n 'syscall:::entry { @[execname] = count(); }'

# Какие файлы открываются?
dtrace -n 'syscall::openat:entry { printf("%s %s", execname, copyinstr(arg1)); }'

# Распределение латентности read() (гистограмма)
dtrace -n 'syscall::read:entry { self->ts = timestamp; }
  syscall::read:return /self->ts/ {
    @["ns"] = quantize(timestamp - self->ts);
    self->ts = 0;
  }'

# Кто создаёт новые процессы?
dtrace -n 'proc:::exec-success { printf("%s -> %s", curpsinfo->pr_psargs, args[0]); }'

# Какие процессы вызывают запись на диск? (BIO_WRITE == 2, BIO_READ == 1)
dtrace -n 'io:::start /args[0]->bio_cmd == 2/ { @[execname] = count(); }'

В примере с файлами намеренно стоит openat, а не open*: libc реализует open(2) через openat(AT_FDCWD, ...), поэтому почти все открытия проходят именно через openat, а путь в нём лежит не в arg0 (там дескриптор каталога), а в arg1.

Каждый из этих однострочников безопасен для production — DTrace спроектирован так, что probe без активного consumer не влияет на производительность.

Начиная с FreeBSD 14.1 dtrace(1) умеет отдавать машиночитаемый вывод через libxo(3): dtrace --libxo или -x oformat=json|xml|html (text — обычное человекочитаемое поведение). Полезно, когда результат разбирает не человек, а скрипт. Нюанс: в этом режиме dtrace не печатает ничего, пока явно не вызваны функции печати, — агрегации приходится выводить самому либо добавлять флаг -O, который печатает их все при выходе.

DTrace Toolkit

# После установки sysutils/dtrace-toolkit
/usr/local/share/dtrace-toolkit/

hotkernel              # какие функции ядра потребляют CPU
procsystime            # системное время по процессам
opensnoop              # трассировка open() в реальном времени
execsnoop              # трассировка exec() — кто что запускает
rwsnoop                # трассировка read/write
iosnoop                # I/O операции
tcpsnoop               # TCP-соединения

Симлинки в /usr/local/bin порт делает только для dtruss, hotkernel, procsystime, opensnoop и shellsnoop; остальные скрипты запускаются по полному пути из этого каталога. Не всё из тулкита работает на FreeBSD как есть — Handbook предупреждает об этом прямо. Скрипты, специально портированные на FreeBSD, лежат в базовой системе, в /usr/share/dtrace; а, например, tcpsnoop в собственной шапке признаётся, что построен на fbt-пробах конкретной версии ядра Solaris 10, и на FreeBSD его придётся переписывать.

opensnoop и execsnoop — вероятно, два самых практически полезных скрипта. Первый показывает все открытия файлов в системе (помогает найти "какой конфиг ищет программа"), второй — все запуски процессов (помогает понять, что делает cron/rc/скрипт).

Когда DTrace, а когда хватит проще

top/vmstat/iostat — первичная диагностика, достаточно для 80% ситуаций.

truss — когда нужно понять поведение конкретного процесса.

procstat — когда процесс заблокирован и нужно понять на чём.

DTrace — когда нужно ответить на вопрос, который невозможно задать стандартными инструментами: "какие процессы записывают более 1MB за раз?", "какие TCP-соединения имеют латентность выше 100ms?", "какая функция ядра вызывается при определённом условии?".

Диагностика типичных проблем

Система "тормозит" — алгоритм

  1. top — CPU idle? Если близко к 0 → CPU-bound: кто ест CPU (top -o cpu)
  2. vmstat 1 — pi/po ненулевые? → система свопит: top -o res, уменьшить ARC
  3. iostat -x 2 — %b близко к 100? → I/O bottleneck: gstat, кто пишет/читает
  4. netstat -s — ретрансмиссии растут? → сетевые потери
  5. dmesg — ошибки hardware?

Процесс "повис"

procstat -k <PID>                  # стек ядра — на чём заблокирован
truss -p <PID>                     # какой syscall выполняет
kill -INFO <PID>                   # некоторые программы покажут состояние (SIGINFO)

kill -INFO (Ctrl+T в терминале) — уникальная BSD-фича. Отправляет SIGINFO процессу, и многие стандартные утилиты (dd, cp, tar, fetch) выводят прогресс. Работает и для пользовательских программ, если они обрабатывают этот сигнал.

Нехватка дискового пространства

df -h                              # общая картина
du -hxd 1 /                        # размеры каталогов первого уровня
zfs list -o name,used,usedbysnapshots   # ZFS: снепшоты могут занимать место!

# Частая причина: забытые снепшоты
zfs list -t snapshot -o name,used -s used   # снепшоты по занимаемому месту

Сервис не запускается

service <name> start               # попытка запустить
cat /var/log/messages | grep <name>   # что в логах
truss service <name> start         # трассировка — что пытается открыть/сделать
sockstat -l | grep <port>          # порт уже занят?

Мониторинг для production

Инструменты выше — для интерактивной диагностики. Для long-term мониторинга:

bsnmpd(8) — SNMP-демон из base system. Минималистичный, достаточный для сбора базовых метрик внешним коллектором (Zabbix, Prometheus через SNMP exporter, MRTG).

node_exporter (sysutils/node_exporter) — Prometheus-совместимый экспортёр метрик. Наиболее современный подход для интеграции с Grafana/Prometheus стеком.

collectd (net-mgmt/collectd5) — лёгкий демон сбора метрик с поддержкой множества backends.

periodic(8) — встроенная система ежедневных/еженедельных/ежемесячных проверок. Генерирует отчёты и отправляет email root'у:

# /etc/periodic.conf
daily_status_security_enable="YES"
daily_status_disks_enable="YES"
daily_scrub_zfs_enable="YES"
daily_status_zfs_enable="YES"
daily_status_network_enable="YES"

Эти отчёты — минимальный мониторинг, который должен быть на каждом сервере.

Отличия от Linux

truss → strace. Аналогичная функциональность, разные имена.

procstat → частично /proc/<PID>/*, частично lsof. В FreeBSD /proc минимален (и вообще не монтируется по умолчанию), procstat заменяет его.

gstat → нет прямого аналога. iostat в Linux ближе всего.

systat → нет аналога в base system Linux. Ближайшее — dstat (сторонний пакет), но сам dstat заброшен: репозиторий заархивирован в ноябре 2020 года, а разработка продолжается в форке dool.

DTrace → bpftrace/eBPF. Исторически DTrace появился раньше, bpftrace вдохновлён им. Синтаксис похож, но экосистемы разные.

kill -INFO (SIGINFO) → не существует в Linux. Уникальная BSD-фича.

periodic → аналога в base system Linux нет. Ближайшее — самодельные скрипты в cron или systemd timers.

Brendan Gregg (автор USE Method и DTrace Toolkit) опубликовал USE Method checklist для FreeBSD — систематический подход к диагностике по ресурсам (Utilization, Saturation, Errors). Рекомендую как reference.

Источники


Связанные заметки

Из библиотеки института уносят только знания. Читателей здесь не считают: посещение не регистрируется, отметок в издании не остаётся, счётчиков нет ни у одного издания фонда.

Издание пополняется и пересверяется. Текст доступен на условиях CC BY-SA 4.0 — унесённое можно передавать дальше на тех же условиях.