Один разбор вместо десяти вкладок: с чего начать, когда «всё тормозит», как отличить нехватку CPU от дискового I/O и swap, где искать OOM killer и кончившиеся inode, и что приложить к тикету, если дело в хосте.
Сервер тормозит - что делать в первую очередь: не гадать, а за пару минут снять показания. Ниже - порядок действий для Linux (Ubuntu 22.04, 24.04, 26.04 и Debian): сначала общая картина через uptime и top, потом разбор по симптому - процессор, память и swap, дисковый I/O, сеть. Плюс как читать load average, что такое CPU steal и inode, и что приложить к тикету, если окажется, что дело в хосте, а не в вашем коде.
TL;DR. Начните с
uptime(load average) иtopлибоhtop. Высокий load при занятом процессоре - смотритеps aux --sort=-%cpu | headиpidstat 1 5. Высокий load при простаивающем процессоре - ищите процессы в состоянии D (ps -eo state,pid,comm,wchan:32 | grep '^D') и проверяйте диск черезiostat -xz 1(столбцы%util,r_await). Память:free -h(столбецavailable),vmstat 1(si/so- активный swap),sudo dmesg -T | grep -i oom- не убивал ли процессы OOM killer. Сеть:ss -sиsudo ss -tlnp. Диск заполнен, но место есть поdf -h- проверьте inode черезdf -i. Часть инструментов не стоит по умолчанию:sudo apt install sysstat iotop htop.
uptime показывает три числа load average и время работы без перезагрузки. top - живая таблица процессов плюс строки сводки по процессору и памяти. htop, если он поставлен, - тот же top с цветом, деревом процессов и мышью; на свежем сервере его обычно нет.
uptime
nproc
top
uptime - три значения load average (за 1, 5 и 15 минут) и аптайм.nproc - число доступных ядер (vCPU). Load сравнивают именно с ним.top - интерактивный, выход по q. Полезные клавиши: P - сортировка по CPU, M - по памяти, 1 - разбить нагрузку по ядрам.Что вы должны увидеть. В шапке top - строка %Cpu(s) с полями us, sy, id, wa, st и строки MiB Mem / MiB Swap. Ниже - процессы. Первым делом читайте строку %Cpu(s): она сразу говорит, во что вы упёрлись - в вычисления (us), в ядро (sy), в диск (wa) или у вас отбирают процессор (st).
ss, journalctl, top, free, vmstat, ps, df, du, dmesg, swapon обычно уже есть в стандартных образах Ubuntu и Debian (в сильно урезанных cloud- и контейнерных образах может не быть и их). А вот iostat, pidstat и mpstat приходят в пакете sysstat; iotop, htop и, для графика трафика, nload или iftop - отдельными пакетами.
sudo apt update
sudo apt install sysstat iotop htop
nload и iftop ставятся так же, по необходимости. Ставить весь список заранее не обязательно - хватит того, что нужно под конкретный симптом.
Load average - усреднённое за 1, 5 и 15 минут число потоков, которые либо выполняются на процессоре, либо стоят к нему в очереди, либо находятся в состоянии непрерываемого сна. D-state (непрерываемый сон) - процесс застрял в системном вызове, обычно на дисковом или сетевом I/O, и не реагирует даже на kill -9, пока операция не завершится. Ключевой момент: в Linux load считает и D-state, а не только процессорную очередь. Поэтому load 20 при почти простаивающем процессоре - это не сломанный датчик, а два десятка процессов, зависших в ожидании медленного диска или сетевой файловой системы.
Как читать три числа: 1-минутное - что происходит сейчас, 15-минутное - тренд. 1-минутное заметно выше 15-минутного - нагрузка растёт; ниже - спад. Ориентир по величине: устойчивый 1-минутный load примерно на уровне числа ядер (nproc), если его создают в основном готовые считать задачи, - все ядра заняты без большой очереди (сверьтесь со строкой %Cpu(s) в top: если велик wa, дело не в процессоре); значительно выше числа ядер - процессы стоят в очереди, и надо понять, за что они борются: за CPU (тогда в top большой us или sy) или за I/O (большой wa, процессы в состоянии D).
Условный пример строки (числа только для иллюстрации): %Cpu(s): 2.0 us, 1.3 sy, 0.0 ni, 8.0 id, 88.0 wa, 0.0 hi, 0.7 si, 0.0 st - процессор почти всё время простаивал при незавершённых операциях ввода-вывода. Load высокий, а виноват не процессор. Большой wa - сильный повод проверить диск, но не приговор именно диску: в состояние D уводит и сетевая файловая система. Список зависших процессов: ps -eo state,pid,comm,wchan:32 | grep '^D'.
top уже сказал, куда уходит процессорное время. Расшифровка строки %Cpu(s):
us (user) - код приложений в пространстве пользователя. Высокий us - какая-то программа реально считает.sy (system) - работа ядра: системные вызовы, переключения контекста, обработка сети. Высокий sy при низком us - подозрительно много системных вызовов (иногда кривой код, иногда шторм пакетов).wa (ожидание ввода-вывода) - доля времени, когда процессор простаивал при незавершённой операции ввода-вывода. Это не занятость процессора, а его вынужденный простой; на многоядерной системе это грубый индикатор, а не точная «доля ожидания диска». Большой wa уводит в раздел про диск.st (steal) - время, когда ваша виртуальная машина была готова считать, но гипервизор не дал ей процессорное время: занял его другими задачами на хосте. Короткие всплески st сами по себе ещё не проблема; устойчивый st, совпадающий по времени с просадкой, - признак того, что хост переподписан. Значения порядка 10% и выше особенно заметны для счётных нагрузок, но универсального порога нет.ps aux --sort=-%cpu | head
pidstat 1 5
ps aux --sort=-%cpu | head - топ процессов по CPU. Оговорка: %CPU здесь - среднее за всё время жизни процесса, недавний всплеск он занижает. Для «прямо сейчас» точнее top или pidstat.pidstat 1 5 - пять замеров с интервалом в секунду, загрузка CPU по процессам в динамике. %usr против %system - то же деление, что us/sy, но по конкретному процессу.Если высокий именно st, а не us - дело не в вашем коде: гипервизор не выделяет вашему vCPU процессорное время достаточно часто (обычно из-за переподписки хоста), и это уже вопрос к хостеру или тарифу (выделенные ядра, план с гарантированным CPU). Снимите mpstat 1 за несколько минут и приложите к тикету.
free -h - первое по памяти. Значимый столбец - available: сколько памяти приложения могут занять без вытеснения в swap. Столбец buff/cache пугать не должен - это кэш файловой системы, ядро отдаст его под нужды приложений.
swap (раздел или файл подкачки) сам по себе не зло. Проблема - пробуксовка подкачки: оперативной памяти не хватает, и ядро непрерывно гоняет страницы память - диск - память. Формально память есть, но каждое обращение к ней идёт через диск, и сервер замедляется в разы. Со стороны это выглядит как «тормозит вообще всё».
free -h
vmstat 1 5
swapon --show
free -h - смотрите available, а не free.vmstat 1 5 - столбцы si и so (подкачка в память и из памяти, КиБ/с). Нули означают, что прямо сейчас обмена со swap нет; сам swap при этом может быть занят - его объём смотрите в столбце swpd, в free -h или swapon --show. Стабильно ненулевые si/so - идёт активная подкачка, вот и тормоза. Ещё столбцы: r - очередь на процессор, b - процессы в непрерываемом сне. Первый отчёт vmstat - средние с момента загрузки; смотрите со второго или запускайте vmstat -y 1 5, чтобы его пропустить.swapon --show - есть ли swap и сколько занято. Пустой вывод - swap не настроен; тогда при нехватке памяти ядро сперва освобождает страничный кэш и другую освобождаемую память, а если и этого мало - вызывает OOM killer.Если процесс внезапно пропал - без записи в своих логах, без ошибки - вероятно, его убил OOM killer: механизм ядра, который срабатывает, когда запрос памяти нельзя удовлетворить в доступных процессу пределах. Это либо глобальная нехватка ОЗУ и swap, либо лимит памяти cgroup или контейнера (memory.max) - тогда OOM приходит внутри контейнера, даже если на хосте память ещё есть. Жертву ядро выбирает по «badness»-оценке (на неё влияет и oom_score_adj).
sudo dmesg -T | grep -i -E 'oom|killed process'
journalctl -k -b | grep -i 'out of memory'
dmesg -T - кольцевой буфер ядра; -T переводит отметки времени в человеческий вид. Нужен sudo: чтение dmesg на Ubuntu по умолчанию закрыто.journalctl -k -b - сообщения ядра за текущую загрузку. Строка вида Out of memory: Killed process 1234 (mysqld) - и есть ответ: кто и когда.Здесь два разных вопроса: диск не тянет по скорости - или на диске кончилось место либо inode.
Скорость. iostat -xz 1 - расширенная статистика по устройствам, -z скрывает бездействующие. Первый отчёт - средние с момента загрузки, смотрите второй и дальше.
iostat -xz 1
sudo iotop -o
pidstat -d 1 5
iostat -xz 1: столбец %util - доля времени, когда на устройстве была хоть одна операция. Для обычного диска близко к 100% - насыщение; для NVMe %util вводит в заблуждение (устройство держит сотни параллельных операций и показывает 100% далеко не на пределе), поэтому там смотрите r_await / w_await - среднее время чтения/записи в миллисекундах с учётом очереди - и aqu-sz (средняя длина очереди). Десятки миллисекунд на SSD - подозрительно.iotop -o (пакет iotop, запуск от root): -o показывает только процессы, которые прямо сейчас читают или пишут. Объём чтения и записи по процессам он показывает и без дополнительной настройки; а вот колонка процента времени в ожидании ввода-вывода и SWAPIN завязаны на delay accounting, которое на ядрах 5.14+ (все текущие Ubuntu и Debian) по умолчанию выключено. Если эти колонки нужны, временно включите его: sudo sysctl kernel.task_delayacct=1, а после диагностики верните =0 - постоянно держать его включённым смысла нет. Простая альтернатива без настройки - pidstat -d ниже.pidstat -d 1 5 - альтернатива iotop из sysstat: kB_rd/s и kB_wr/s по процессам.Место. df -h - занятость разделов в человеческих единицах. Раздел под 100% - найдите, что распухло:
df -h
sudo du -xh --max-depth=1 / | sort -h
du -xh --max-depth=1 / - размер каждого каталога в корне; -x не уходит на другие файловые системы (иначе посчитаете /proc и точки монтирования). Повторяйте вглубь по самому большому каталогу. Обычные виновники - /var/log, кэши, дампы, забытые бэкапы.Inode. Бывает так: df -h показывает свободные гигабайты, а запись падает с No space left on device. Самая частая причина - закончились inode, записи файловой системы, по одной на каждый файл или каталог (хранят права, владельца, время, указатели на данные). Реже виноваты дисковая квота или лимит контейнера. Число inode на ext4 фиксируется при создании файловой системы и не растёт; XFS выделяет их динамически и в это почти не упирается.
df -i
df -i - то же, что df -h, но про inode. IUse% на 100% при свободном месте - типичная картина: миллионы мелких файлов (сессии, письма, кэш, застрявшая очередь задач). Дальше - du --inodes или find по каталогам, чтобы найти источник.ss - штатная замена netstat, ставить ничего не нужно.
ss -s
sudo ss -tlnp
ss -tn state established | wc -l
ss -tn state time-wait | wc -l
ss -s - сводка: сколько всего сокетов и сколько TCP в каждом состоянии.ss -tlnp - какие TCP-порты слушаются и каким процессом (t - TCP, l - слушающие, n - без резолва портов в имена, p - процесс; p требует root). Первое, что проверяют, когда «сервис не отвечает»: слушает ли он вообще и на том ли адресе (127.0.0.1 против 0.0.0.0).ss -tn state established | wc -l - число установленных соединений.ss -tn state time-wait | wc -l - соединения в TIME-WAIT (нормальное состояние примерно на минуту после закрытия). Десятки тысяч - высокая текучка соединений; на нагруженном публичном сервисе это может быть нормой. Тревожно, если параллельно кончаются исходящие порты или файловые дескрипторы либо растёт задержка - тогда смотрите keep-alive, пул соединений к базе и характер трафика.Пропускную способность в реальном времени показывают nload и iftop (оба - отдельные пакеты, iftop запускается от root).
Когда служба отвалилась, ответ почти всегда в логах.
journalctl -p err -b
journalctl -u имя-службы -e
journalctl -f
sudo dmesg -T | tail -n 50
journalctl -p err -b - сообщения уровня error и выше за текущую загрузку (-b). Быстрый способ увидеть, что ругалось.journalctl -u имя-службы -e - лог конкретной службы, -e прокручивает в конец. Имя - как в systemctl status (например nginx, ssh, docker).journalctl -f - хвост журнала в реальном времени; воспроизведите проблему и смотрите, что появляется.dmesg -T - если дело в железе, диске или сети на уровне ядра: ошибки файловой системы, сброс сетевого адаптера, тот же OOM.systemctl и journalctl в работе можно посмотреть в нашем гайде по настройке веб-сервера Caddy.
Симптом | Первая команда | На что смотреть | Вероятная причина |
|---|---|---|---|
Load высокий, реакция вялая |
| 1-минутный load против числа ядер | load намного выше числа ядер - очередь на CPU или на I/O |
Load высокий, но процессор в основном простаивает |
| большой | процессы ждут ввода-вывода - чаще диск, иногда сетевая ФС |
CPU занят почти на 100% |
| какой процесс, | приложение считает или слишком много системных вызовов |
В |
| устойчивый | хост переподписан - вопрос к хостеру |
Всё медленно, диск постоянно шуршит |
|
| нехватка памяти, идёт swap |
Процесс внезапно исчез | | строка | процесс убил OOM killer |
| |
| кончились inode - много мелких файлов |
Раздел заполнен |
| какой каталог распух | логи, кэш, дампы, старые бэкапы |
Служба не отвечает по сети | | слушает ли нужный порт и на том ли адресе | служба упала или слушает |
Соединений очень много |
| десятки тысяч в TIME-WAIT | высокая текучка; проблема, только если кончаются порты/дескрипторы или растёт задержка |
Если вы сузили проблему до того, что дело в хосте (высокий st, странные ошибки диска в dmesg, сеть проседает без роста трафика), соберите факты один раз - это экономит круг переписки:
uptime и nproc;top -b -n1 | head -20 - снимок без интерактива;free -h, а также df -h и df -i;iostat -xz 1 5 - пять замеров;ss -s;journalctl -p err -b и sudo dmesg -T | tail;st - mpstat 1 за несколько минут.CPU steal, ошибки контроллера диска, потери пакетов на шлюзе - это не чинится изнутри виртуальной машины, это зона хостера.
В Linux load average считает не только процессы на CPU и в очереди к нему, но и застрявшие в непрерываемом сне (D-state) - обычно в ожидании диска или сетевой файловой системы. Поэтому load 20 при простаивающем процессоре часто означает не нехватку процессора, а ожидание ввода-вывода - чаще всего диска, иногда сетевой файловой системы. Найдите зависшие процессы (ps -eo state,pid,comm,wchan:32 | grep '^D') и подтвердите по столбцу wa в top и по iostat -xz 1.
Откройте top и нажмите P (сортировка по CPU) либо запустите pidstat 1 5 для нескольких замеров подряд. ps aux --sort=-%cpu | head тоже даст список, но его %CPU - среднее за всю жизнь процесса, поэтому недавний всплеск он занижает.
Steal (столбец st в top) - время, когда ваша виртуальная машина готова считать, но гипервизор занял физическое ядро другим клиентом. Короткие всплески - не проблема; устойчивый st, совпадающий по времени с просадкой, - признак переподписки хоста (порядок 10% и выше особенно заметен для счётных нагрузок). Изнутри виртуальной машины это не лечится: снимайте mpstat 1 и идите к хостеру за выделенными ядрами или другим тарифом.
Чаще всего кончились inode - служебные записи файловой системы, по одной на файл или каталог. Проверьте df -i: если IUse% равен 100 при свободных гигабайтах, дело в этом (реже - дисковая квота или лимит контейнера). Обычно виноваты миллионы мелких файлов - сессии, кэш, письма, застрявшая очередь задач.
sudo dmesg -T | grep -i 'killed process' или journalctl -k -b | grep -i 'out of memory'. Строка вида Out of memory: Killed process 1234 (name) с отметкой времени - это он. Причина - ядру не хватило памяти в доступных процессу пределах: глобально (ОЗУ и swap) или по лимиту cgroup/контейнера. Смотрите free -h и что росло по памяти в top; для контейнера - его лимит и memory.current.
Запустите vmstat 1. Ненулевые и не спадающие столбцы si/so - идёт активная подкачка страниц через диск, отсюда общая вялость. При нехватке CPU si/so по нулям, зато растёт столбец r (очередь на процессор) и us/sy в top.
По умолчанию нет iostat, pidstat, mpstat (пакет sysstat), а также iotop, htop, nload, iftop - каждый ставится отдельно. Обычно уже есть в стандартных образах: top, free, vmstat, ps, ss, journalctl, dmesg, df, du, swapon.
Для разбора «прямо сейчас» разницы почти нет. htop удобнее визуально - дерево процессов, цвета, прокрутка, снятие процесса по F9. top есть всегда и умеет пакетный режим (top -b -n1) для снимка в файл или тикет. Ставьте htop для повседневного, top держите как запасной.
uptime и top - общая картина, потом разбор по симптому.%Cpu(s): us - приложения, sy - ядро, wa - ожидание ввода-вывода, st - время, отобранное гипервизором.available в free -h; активный swap виден в si/so у vmstat 1; убитые процессы - в dmesg по слову oom.iostat -xz 1 (r_await, %util) для скорости, df -h для места, df -i для inode.ss -s для сводки, ss -tlnp - кто слушает порт, счёт TIME-WAIT - для оценки текучки соединений.iostat, pidstat, iotop, htop, nload ставятся отдельно; ss и journalctl обычно уже на месте.dmesg - зона хостера: снимите показания и в тикет.