· 17 мин чтения

Как диагностировать тормоза Linux-сервера: чек-лист сисадмина

«Сервер тормозит» — самое расплывчатое описание проблемы, которое я слышу регулярно. За 15 лет работы в АйТи Фреш я выработал чёткий алгоритм: от первой минуты подключения по SSH до постановки точного диагноза за 20-30 минут. В этой статье — мой пошаговый чек-лист с командами, интерпретацией вывода и типичными находками.

Первые 60 секунд: общая картина

Когда падает звонок «у нас всё медленно», я начинаю не с глубоких профилировщиков, а с двух команд. За минуту они дают 80% понимания, что происходит на сервере. Это методология Брендана Грегга, и я с ней согласен полностью.

uptime
dmesg -T | tail -30
vmstat 1 5
mpstat -P ALL 1 5
pidstat 1 5
iostat -xz 1 5
free -m
sar -n DEV 1 5
sar -n TCP,ETCP 1 5
top -b -n 1 | head -25

Эти десять команд за 60 секунд дают полный срез по CPU, памяти, диску, сети и активным процессам. Я держу их в скрипте /usr/local/bin/perf60 на каждом сервере, который сопровождаю.

На что смотрю в первую очередь:

CPU: горит ли процессор

Если по vmstat видно высокое us% (user) или sy% (system), а wa% (iowait) низкое — узкое место в CPU. Дальше нужно понять, какие процессы и какие функции внутри них съедают такты.

Шаг 1. top или htop. Сортировка по %CPU, видим топ-5 процессов.

htop -d 5 -s PERCENT_CPU

Если в топе один процесс и съедает 100-400% CPU (это значит, что он использует 1-4 ядра полностью) — проблема локализована. Если CPU размазан между десятками процессов — проблема системная, ищем причину в нагрузке.

Шаг 2. mpstat по ядрам. Иногда «загрузка 25%» на 4-ядерной системе означает, что одно ядро забито на 100%, а остальные простаивают. Это классика для однопоточного приложения.

mpstat -P ALL 1 10

Если %usr на одном ядре = 100, а на остальных близко к нулю — приложение однопоточное и упёрлось в одно ядро. Решение: либо параллелить (если возможно), либо переходить на CPU с большей одноядерной производительностью.

Шаг 3. perf top для глубокого анализа.

perf top -p $(pgrep -d, java)
# или для всей системы
perf top -g

Видим, в каких функциях сжигается процессор. Часто оказывается, что приложение крутится в каком-нибудь regex-движке или в неоптимальном GC. У одного клиента в 2025 году нашёл, что 60% CPU PostgreSQL уходило на парсинг повторяющегося SQL-запроса — помог prepared statement.

Шаг 4. Если приложение чужое или закрытое — strace и ltrace.

sudo strace -c -p $(pgrep -f myapp)
# Останавливаем через 10-15 секунд Ctrl+C, видим распределение syscalls
sudo ltrace -f -c ./myapp
# Покажет вызовы библиотечных функций

Если в strace -c доминируют read/write на маленьких блоках (4-32 байта) — приложение тратит время на syscall overhead, нужно либо буферизовать I/O, либо использовать io_uring.

Память: своп, OOM, утечки

Память — самая коварная подсистема. Часто «сервер тормозит» означает, что началась активная подкачка, и каждый запрос превращается в дисковую операцию.

Шаг 1. free -h и понимание буферов.

free -h
              total        used        free      shared  buff/cache   available
Mem:           31Gi        18Gi       1.2Gi       512Mi        12Gi         12Gi
Swap:         4.0Gi       2.1Gi       1.9Gi

Главная цифра — available. Это сколько памяти можно реально выделить новому процессу с учётом возможности освободить кеши. Если available меньше 10% от total — пора смотреть детально. Если в swap используется больше 1 ГБ и swap-in/out активный — уже проблема.

Шаг 2. vmstat для динамики свопа.

vmstat 1 30
# Смотрим колонки si (swap in) и so (swap out)

Если si/so стабильно больше 0 — система активно своппит. Каждая swap-in операция — это чтение с диска, что в десятки тысяч раз медленнее RAM. Если SSD под swap — терпимо, если HDD — катастрофа.

Шаг 3. Кто потребляет память — smem.

sudo apt install smem
sudo smem -k -s pss -r | head -20

В отличие от ps, smem показывает PSS (Proportional Set Size) — реальное потребление с учётом разделяемых библиотек. Для приложений, которые форкают много процессов (типа nginx workers), PSS даёт честную картину.

Шаг 4. Утечки памяти — /proc/PID/smaps_rollup.

cat /proc/$(pgrep -f myapp)/smaps_rollup
# Снимаем дважды с интервалом в час, сравниваем Rss и Pss

Если Rss растёт линейно при стабильной нагрузке — утечка. Дальше — valgrind для C/C++, pprof для Go, py-spy для Python. У одного клиента нашли утечку в самописном экспортере метрик: каждый запрос на /metrics забывал закрыть соединение к БД, через сутки подъедало 8 ГБ.

Шаг 5. OOM-killer — анализ по dmesg.

dmesg -T | grep -i 'killed process\|oom-killer'
# Пример вывода:
# [Thu Apr 17 03:14:22 2026] Out of memory: Killed process 12345 (java) total-vm:8388608kB...

Если OOM-killer убил критичный процесс — нужно либо увеличить RAM, либо ограничить память других процессов. Я предпочитаю второе через systemd:

# /etc/systemd/system/myapp.service.d/limits.conf
[Service]
MemoryHigh=4G
MemoryMax=6G
MemorySwapMax=0
OOMScoreAdjust=-500

OOMScoreAdjust=-500 говорит ядру: «убивай этот процесс в последнюю очередь». Полезно для критичных сервисов вроде PostgreSQL.

Диск: IOPS, latency, очереди

Диск — самое частое узкое место в офисных серверах. RAID 5 на SATA-дисках под нагрузкой 1С способен превратить любой сервер в кисель.

Шаг 1. iostat -x для расширенной статистики.

iostat -xz 1 10
# Ключевые столбцы:
#   r/s, w/s — IOPS чтения/записи
#   rkB/s, wkB/s — пропускная способность
#   await — средняя задержка операции в мс
#   %util — загрузка устройства

Норма для SSD: %util до 80% при await менее 5 мс. Для HDD: %util до 70% при await менее 20 мс. Если await > 50 мс или %util держится на 95+ — диск перегружен. Если await взлетает в момент бэкапа или ребилда RAID — это объяснимо. Если постоянно — нужно либо ускорить диск, либо разнести нагрузку.

Шаг 2. Кто грузит диск — iotop.

sudo iotop -oPa
# -o только активные процессы
# -P только процессы (не потоки)
# -a накопленные значения

Иногда выясняется, что 70% дисковой нагрузки — это journald, который пишет логи в синхронном режиме. Лечится переключением в asynchronous через SyncIntervalSec=5min в /etc/systemd/journald.conf.

Шаг 3. Глубокая трассировка дисковых операций — eBPF.

sudo apt install bpfcc-tools
sudo biolatency-bpfcc 5 1
# Гистограмма задержек дисковых операций за 5 секунд
sudo biosnoop-bpfcc
# Live-выдача каждой дисковой операции: PID, диск, тип, размер, latency

biolatency показывает распределение задержек — если хвост в районе 50-100 мс заметный, значит, есть периодические тормоза, которые усредняются и невидны в iostat. У одного клиента так нашли проблемный диск в RAID 6: на iostat по массиву всё было ок, на biosnoop увидели, что один из дисков выдаёт latency в 200+ мс на запись.

Шаг 4. SMART-статус и износ.

sudo smartctl -a /dev/sda
# Смотрим:
#   ID 5 — Reallocated_Sector_Ct (>0 — диск умирает)
#   ID 197 — Current_Pending_Sector (>0 — плохие сектора)
#   ID 231 — SSD_Life_Left (на SSD, должно быть >10%)
#   ID 241 — Total_LBAs_Written (на SSD — расход ресурса записи)

Я веду в Zabbix историю по этим показателям и алертю при росте reallocated sectors. Часто это даёт фору в неделю-две до полного отказа диска.

Сеть: потери, задержки, throughput

Сетевые проблемы редко проявляются как «всё медленно», чаще — как «отвалилось 1С» или «сайт не открывается». Но когда симптомы расплывчаты, сеть нужно проверять обязательно.

Шаг 1. ss для активных соединений.

ss -tunap | head -20
# Видим все TCP/UDP соединения с PID процессов

ss -s
# Сводка: количество соединений по типам, состояниям

Если TIME_WAIT соединений тысячи — приложение плохо переиспользует TCP-сессии. Если ESTABLISHED держится десятки тысяч — возможна утечка соединений. Я видел оба случая, и оба чинились правкой пула соединений в приложении.

Шаг 2. sar -n DEV для трафика интерфейсов.

sar -n DEV 1 5
# Колонки:
#   rxpck/s, txpck/s — пакеты в секунду
#   rxkB/s, txkB/s — пропускная способность
#   rxerr/s, txerr/s — ошибки

Если rxerr или txerr больше нуля — что-то не так с физическим уровнем: бракованный кабель, проблемная NIC, дуплекс рассогласован. ethtool показывает детали:

ethtool eth0
# Speed, Duplex, Auto-negotiation
sudo ethtool -S eth0 | grep -i error
# Hardware error counters: rx_crc_errors, tx_aborted_errors

Особенно коварен rx_crc_errors на гигабитных линках по UTP. Бывает, что сертифицированный кабель работает на скорости передачи данных, но на длинных дистанциях даёт ошибки. Помогает либо замена кабеля, либо принудительная установка скорости 100 Мбит:

sudo ethtool -s eth0 speed 100 duplex full autoneg off

Шаг 3. tcpdump для конкретных проблем.

sudo tcpdump -i any -nn -w /tmp/cap.pcap host 192.168.1.10 and port 5432
# Захват трафика к PostgreSQL с конкретного клиента
# Открываем в Wireshark, смотрим RTT, retransmissions, window size

Если в Wireshark много TCP retransmission — пакеты теряются по дороге. Если zero window — получатель не успевает обрабатывать.

Шаг 4. Современная альтернатива — tcptracer-bpfcc и tcpconnect-bpfcc.

sudo tcpconnect-bpfcc
# Live-список новых TCP-соединений с указанием процесса
sudo tcpretrans-bpfcc
# Live-список retransmission с PID и временем

Это позволяет в реальном времени видеть, какой процесс открывает куда соединения и где теряются пакеты. До eBPF такие задачи решались только через сложные настройки systemtap.

Кейс из практики: 1С-сервер тормозил по вечерам

Реальный случай января 2026 года. Клиент: офис 40 РМ, сервер 1С на Ubuntu, PostgreSQL 16. Жалоба: с 16:30 до 18:00 проведение документов начинает тормозить, к 17:30 интерфейс почти не отвечает, в 18:30 всё налаживается.

Что я делал по шагам:

  1. 16:35. Подключился по SSH. uptime показал load average 18.5/12.3/8.2 при 8 ядрах. Перегрузка свежая, нарастает.
  2. 16:36. top: PostgreSQL съедает 600% CPU (6 ядер из 8), 1С — 200% (2 ядра). Процессов postgres много, видимо, активные сессии.
  3. 16:38. mpstat -P ALL: загрузка размазана, не однопоточная проблема.
  4. 16:40. iostat -x: %util диска 95%, await 80 мс, разрывы под бэкап в 17:00. Странно, бэкап ещё не запустился.
  5. 16:42. iotop -oPa: pg_dump потребляет 250 МБ/с чтения. Кто-то запустил дамп в рабочее время!
  6. 16:44. ps aux | grep pg_dump: дамп запустил Cron-задание клиента, которое они сами поставили месяц назад «для подстраховки».
  7. 16:45. Убил pg_dump, нагрузка на диск упала за минуту, тормоза в 1С прекратились через 3 минуты.

Диагноз: дублирующий бэкап перекрывался с пиковой нагрузкой пользователей. Решение: убрали лишний cron, бэкап остался один — наш ночной через Borg. На будущее повесил Zabbix-триггер на запуск pg_dump в рабочее время.

Время диагностики — 12 минут. Без структурированного подхода ушло бы полдня на «давайте сначала перезагрузим сервер».

Профилактика: метрики в Zabbix

Реактивная диагностика хороша, но проактивная лучше. На каждом сервере я снимаю минимум 30 ключевых метрик в Zabbix с разной частотой:

ПодсистемаМетрикаТриггер
CPUload average 5min, %iowait, %stealload > 2× ядер за 15 мин; iowait > 30%
Памятьavailable, swap used, OOM eventsavailable < 10%; swap > 1 ГБ; любой OOM
Диск%util, await, IOPS, free spaceutil > 90% за 10 мин; await > 50 мс
Сетьtraffic, errors, retransmitserrors > 0; retrans > 1% от трафика
SMARTreallocated, pending, life_leftreallocated > 0; life_left < 10%
Сервисыprocess count, port listen, response timeсервис упал; LCP > 3 сек; RPS < baseline-30%

Алерты идут в Telegram дежурного. Тренды сохраняются на 90 дней — этого хватает, чтобы сравнить «как было до изменения» и «как стало после».

Чек-лист, который я держу под рукой

Краткая карточка для быстрого подключения к проблемному серверу:

  1. uptime — состояние нагрузки.
  2. dmesg -T | tail -50 — что говорит ядро.
  3. vmstat 1 5 — общий обзор r/b/si/so/wa.
  4. top -b -n 1 | head -20 — топ процессов.
  5. free -h — память.
  6. iostat -xz 1 5 — диски.
  7. sar -n DEV 1 5 — сеть.
  8. ss -s — сводка соединений.
  9. journalctl -p err -n 100 — критичные ошибки сервисов.
  10. df -h && df -i — место и inodes.

За 5-7 минут эти десять команд покрывают 90% диагностики. Дальше — углубляться в perf, eBPF и tcpdump в зависимости от того, какая подсистема всплыла.

Что не работает: антипаттерны диагностики

За годы насмотрелся на распространённые ошибки коллег:

«Перезагрузим — посмотрим». Перезагрузка сбрасывает контекст, и причина теряется. Сначала собрать sosreport или sar history, потом перезагружать (если уж очень нужно).

«У нас памяти всё хорошо, видишь — used маленький». Используется значение used вместо available. На современных Linux буферы и кеш считаются как used, но фактически освобождаются по требованию. Смотреть надо available.

«Я просто увеличил CPU/RAM, должно помочь». Без понимания root cause увеличение ресурсов лишь отодвигает проблему. У одного клиента трижды наращивали vRAM на сервере 1С, прежде чем нашли утечку в стороннем расширении конфигурации.

«Логи смотреть не буду, там много». Большинство симптомов уже описано в логах. journalctl с фильтром по приоритету занимает 30 секунд:

journalctl --since "1 hour ago" -p err
journalctl -u myservice.service --since "30 minutes ago"

FAQ

С чего начать диагностику тормозов сервера?
С Load Average (uptime), top или htop. За 30 секунд понятно, какая подсистема перегружена: CPU, диск или памяти не хватает. Дальше углубляемся в детали через iostat, perf и eBPF.

Что такое eBPF и зачем он сисадмину?
eBPF — это виртуальная машина внутри ядра Linux, которая позволяет запускать безопасные программы трассировки. Утилиты bcc-tools и bpftrace показывают, что именно делают процессы: какие syscalls, файловые операции, сетевые соединения. Без eBPF многие вещи раньше требовали пересборки ядра.

Как понять, что узкое место — диск, а не CPU?
Смотрим столбец %iowait в top или vmstat. Если %iowait > 20% при низкой загрузке CPU — упёрлись в диск. Подтверждаем через iostat -x: если %util > 90% и await > 50ms — диск перегружен.

Что делать при OOM-killer на проде?
Сначала смотрим dmesg для понимания, кого убило ядро. Затем настраиваем cgroups через systemd-slice для критичных сервисов с MemoryHigh и MemoryMax. Параллельно ищем утечку через smem и /proc/PID/smaps_rollup.

Сколько стоит аудит производительности Linux-сервера у АйТи Фреш?
Базовый аудит одного сервера — от 25 тысяч рублей: 1-2 дня снятия метрик, анализ, отчёт с конкретными рекомендациями. Если требуется проактивный мониторинг — включаем в абонентский договор.

Тормозит ваш сервер? Поможем разобраться

Если у вас Linux-сервер с непонятными симптомами — закажите экспресс-аудит у АйТи Фреш. За 1-2 дня снимем метрики, найдём узкое место и выдадим план оптимизации. Заявка на itfresh.ru или на 7296241@gmail.com. Если потом возьмёте на сопровождение — стоимость аудита уйдёт в зачёт.

Семёнов Е.С., технический директор АйТи Фреш. 15+ лет в IT-аутсорсинге для бизнеса.