Москва: проверенные б/у ноутбуки с гарантией и проверкой перед оплатой
+7 906 722-94-45

Главная → Статьи → Linux: память, диск, процессы — диагностика разработчика

Память, диск и процессы в Linux: диагностика без админского бэкграунда

Разработчику о ресурсах Linux: free и кеш страниц, почему память «занята», df/du и закончившийся диск, top/ps и съевший CPU процесс, swap и OOM-killer — практический разбор.

Прямой ответ

Три ресурсных вопроса разработчика на сервере решаются шестью командами. Память: free -h — но читать нужно не «used», а available (сколько реально можно выделить: Linux держит свободную память в кеше файлов — «занято 90%» при available 2 ГБ — норма, кеш отдаётся мгновенно; паника по used — главная ошибка новичка); тревожные сигналы — растущий swap-использование и падающий available. Диск: df -h (сколько места на ФС) + du -xh --max-depth=1 / | sort -h (кто съел) — «диск заполнен» в половине случаев логи/кеш/бэкапы без ротации (ротация); отдельный подвох — место есть, а inodes кончились (df -i: миллионы мелких файлов). Процессы: top/htop (кто ест CPU/память сейчас), ps aux --sort=-%mem | head (срез по памяти), для Python — py-spy (чем занят процесс без остановки). И финальный босс: OOM-killer — при исчерпании памяти ядро убивает самый «жирный» процесс (обычно ваше приложение): диагноз — dmesg | grep -i oom или journalctl -k, лечение — лимиты, утечки в приложении, больше RAM. Систематический подход — в статье про диагностику сервера; здесь — минимум, чтобы не звать админа.

Память: кеш, available, swap

free -h показывает: total, used, free, shared, buff/cache, available. Читать так: buff/cache — память, занятая кешем файлов (ядро кеширует прочитанное с диска — повторные чтения быстрее; эта память отдаётся приложениям мгновенно при необходимости — она «занята полезно», не «потрачена»); available — оценка, сколько доступно новому процессу (free + отдаваемая часть кеша) — единственная цифра для решения «хватит ли»; used без available — повод для ложной паники. «Свободная память — потраченная зря память»: Linux намеренно держит кеш полным, и сервер с 100% used / 3 ГБ available здоров. Когда тревожиться: available стабильно <10% под нагрузкой; swap растёт (при достаточной RAM swap почти пуст; активный swap + тормоза — памяти не хватает, начинается thrashing — постоянная перекачка страниц); vmstat 1 — колонки si/so (своп-активность) ненулевые на протяжении минут — дефицит подтверждён. Для приложения: RSS процесса (ps -o rss) против ожиданий; растущий RSS неделями — утечка (objgraph/tracemalloc в Python).

Диск: df, du, inodes и «место есть, а пишется ошибка»

«No space left on device» при свободном месте в GUI — классика с двумя развязками. Первая — inodes: df -i (каждый файл = inode; кеш мелких файлов, сессии PHP, очереди — миллионы файлов исчерпывают inodes при гигабайтах свободного места) — лечение: найти каталог-виновник (find / -xdev -type f | cut -d/ -f2-4 | sort | uniq -c | sort -rn | head), почистить, профилактика — ротация/склейка мелких файлов. Вторая — удалённый открытый файл: файл удалён (rm), но процесс держит его открытым — место не освобождается; lsof +L1 показывает такие («(deleted)» в выводе) — перезапуск процесса освобождает гигабайты; отсюда правило: логи не rm-ить, а ротировать с сигналом/копией (logrotate + copytruncate — настройка). Обычный сценарий поиска: df -h — какой раздел полон; du -xh --max-depth=1 /var | sort -h — спуск к виновнику (обычно /var/log, docker-образы docker system df, старый бэкап-архив). Профилактика: алерт на заполнение >80% (node_exporter + Grafana — дашборды) — диск, заполненный до 100%, роняет базы данных и требует аварийной чистки.

Процессы и CPU: кто тормозит

top (или htop): колонка %CPU — по ядрам или сумме (нагрузочное среднее load average — «очередь задач»: 4.0 на 4-ядерной — граница, выше — процессы ждут CPU; выше числа ядер — дефицит CPU или много IO-ожидания — разделять iowait в топе). ps aux --sort=-%cpu | head -15 — срез топ-процессов; pidstat 1 — динамика по процессам. Для Python-процесса под нагрузкой: py-spy dump --pid N (текущие стеки потоков — чем занят прямо сейчас, без перезапуска и без gdb-магии) и py-spy top (профиль в реальном времени) — связка решает «приложение тормозит» за минуты. Отдельные паттерны: процесс в состоянии D (uninterruptible sleep — ждёт диск/сеть; «висит и не убивается» — часто именно D, лечить причину IO, не kill -9); зомби (Z) — завершённый процесс, которого не пождал родитель (безвредны сами по себе, но сигнал о баге родителя); много спящих клонов — нормально для пула воркеров. Систематизация — USE-метод (Utilization/Saturation/Errors по каждому ресурсу) — в базовой статье по диагностике.

OOM-killer: когда ядро убивает ваше приложение

Симптом: процесс исчез без следа — нет лога остановки, systemd говорит «killed, signal KILL»; причина: память исчерпана, OOM-killer выбрал жертву по oom_score (грубо — самый большой RSS). Диагноз: journalctl -k | grep -i oom / dmesg -T | grep -i kill — видно процесс, его размер и момент. Что делать: (1) понять, норма или аномалия — пиковая нагрузка легитимна (большой отчёт) или утечка (рост неделями — профиль памяти); (2) лимиты вместо сюрпризов — systemd MemoryMax=1500M в юните (юниты): процесс убивается предсказуемо по своему лимиту и перезапускается (Restart=on-failure), а не уносит с собой случайную жертву OOM-killer'а (им может оказаться Postgres); (3) swap как буфер (немного swap на сервере с приложением — страховка от резких пиков, цена — замедление вместо падения; swappiness=10 — ядро предпочитает кеш); (4) мониторинг available/RSS с алертом до катастрофы. Для контейнеров — свой OOM (cgroup-лимиты, 137-й код выхода — Docker-диагностика).

FAQ

Можно ли просто очистить кеш памяти (echo 3 > drop_caches)? Технически да, практически — вред: кеш освободится и тут же начнёт заполняться заново, а первое время всё читается с диска медленнее; «освобождение» памяти для отчётов — борьба с симптомом нормальной работы ядра. Память под приложения отдаётся сама.

Сколько swap нужно серверу с приложением? Небольшой буфер (1–2 ГБ или 10–25% RAM) — страховка от пиков: лучше замедление, чем OOM-kill базы данных; большой swap при дефиците RAM — иллюзия здоровья (thrashing); без swap резкий пик сразу убивает процессы — крайность другая.

Как найти, что заполняет диск, если du виснет? ncdu -x / (интерактивный и быстрый) или du с -x (не уходит на другие ФС) по подозрительным каталогам; проверить удалённые-открытые (lsof +L1) — du их не видит, а место занято; docker — docker system df и docker system prune по политике.

Приложение ест 90% CPU — с чего начать? py-spy dump/top — в каком коде (горячая функция видна сразу: регулярное выражение с катастрофическим бэктрекингом, цикл без выхода, сериализация); если CPU-профиль пуст, а load высокий — смотреть iowait (проблема в диске/сети, не в CPU) и состояние D у потоков.

Источники: man free(1), документация ядра по MM, man oom_kill — ссылки в шапке.