---
tags: [freebsd, tooling]
verified: 2026-09-02
---

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

## Обзор

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

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

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

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

### top

```sh
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

```sh
vmstat 1                           # обновление каждую секунду
```

```text
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 с множеством режимов:

```sh
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: детальный анализ

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

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

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

```sh
# 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

```sh
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.

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

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

```sh
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

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

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

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

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

Для ZFS:

```sh
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

```sh
iostat -x 2                        # расширенная статистика, 2 сек
iostat -d -w 2                     # только диски
```

```text
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

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

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

### ZFS I/O

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

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

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

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

### netstat

```sh
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

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

### tcpdump и pflog

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

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

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

## Логирование

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

```text
/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 при загрузке (сохраняется)
```

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

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

### syslogd

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

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

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

### newsyslog — ротация

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

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

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

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

```sh
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 — трассировка системных вызовов

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

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

### procstat

```sh
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 в документации проекта до сих пор помечен как экспериментальный.

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

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

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

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

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

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

```sh
# Кто делает системные вызовы? (топ процессов по числу 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

```sh
# После установки 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?

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

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

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

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

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

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

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

```sh
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'у:

```sh
# /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](https://www.brendangregg.com/USEmethod/use-freebsd.html) — систематический подход к диагностике по ресурсам (Utilization, Saturation, Errors). Рекомендую как reference.

## Источники

- FreeBSD Handbook, Chapter 28 "DTrace": [docs.freebsd.org/en/books/handbook/dtrace/](https://docs.freebsd.org/en/books/handbook/dtrace/)
- FreeBSD Foundation, "An Introduction to Dynamic Tracing": [freebsdfoundation.org/resource/an-introduction-to-dynamic-tracing/](https://freebsdfoundation.org/resource/an-introduction-to-dynamic-tracing/)
- Klara Systems, "FreeBSD vs. Linux – Tracing and Troubleshooting": [klarasystems.com/articles/freebsd-vs-linux-tracing-and-troubleshooting/](https://klarasystems.com/articles/freebsd-vs-linux-tracing-and-troubleshooting/)
- Brendan Gregg, "USE Method: FreeBSD Performance Checklist": [brendangregg.com/USEmethod/use-freebsd.html](https://www.brendangregg.com/USEmethod/use-freebsd.html)
- `top(1)`, `vmstat(8)`, `iostat(8)`, `systat(1)`, `gstat(8)`, `netstat(1)`, `sockstat(1)`, `truss(1)`, `procstat(1)`, `dtrace(1)`, `pmcstat(8)`, `periodic(8)` — man pages

---

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

- [FreeBSD — sysctl и конфигурация ядра](./freebsd-sysctl-and-kernel.md) — sysctl как основной источник системных счётчиков
- [FreeBSD — ZFS](./freebsd-zfs.md) — диагностика ARC, `zpool iostat`, health пулов
- [Linux — мониторинг и отладка](./linux-monitoring-debugging.md) — journalctl, perf и eBPF, для сравнения с DTrace
- [Linux — средства диагностики производительности](./linux-perf-tools.md) — карта инструментов по слоям системы
- [FreeBSD — сводный cheatsheet](./freebsd-cheatsheet.md) — быстрая справка по диагностическим командам
