Содержание

Linux-процессы, память и системные метрики

Многие backend-программы запускаются на Linux: в Docker-контейнере, на сервере, в Kubernetes или в CI. Даже если вы пишете Go-код, полезно понимать, что происходит под ним: что такое процесс, PID, память, сигналы, файловые дескрипторы и /proc.

Это знание помогает диагностировать реальные проблемы: сервис не останавливается, память растет, порт занят, файлы не закрываются, контейнер убивают по memory limit.

Процесс

Процесс - это запущенная программа. У него есть:

  • PID;
  • память;
  • открытые файлы;
  • переменные окружения;
  • текущая директория;
  • потоки выполнения;
  • права пользователя.

Посмотреть процессы:

ps aux

Интерактивно:

top

Или более удобный вариант, если установлен:

htop

PID нужен, чтобы обратиться к конкретному процессу: посмотреть его файлы, отправить сигнал, изучить потребление ресурсов.

/proc

/proc - виртуальная файловая система с информацией о процессах и системе. Это не обычные файлы на диске. Ядро Linux показывает через них текущее состояние.

cat /proc/meminfo cat /proc/cpuinfo ls /proc/1234

Для процесса:

cat /proc/<pid>/status cat /proc/<pid>/cmdline ls /proc/<pid>/fd

Если вы видите /proc/<pid>/fd, вы смотрите открытые файловые дескрипторы процесса: файлы, сокеты, pipes.

Память

Частые показатели:

  • RSS - физическая память, которую процесс реально занимает сейчас;
  • VSZ/VIRT - виртуальная память, зарезервированная процессом;
  • heap - память для динамических данных;
  • stack - память вызовов функций;
  • swap - память, вытесненная на диск.

Команда:

free -h

Linux активно использует свободную память под disk cache. Это нормально: "used" не всегда значит проблема.

RSS и утечки

Если RSS процесса постоянно растет и не снижается, это повод проверить:

  • не копятся ли данные в map или slice;
  • закрываются ли response body;
  • нет ли goroutine leak;
  • не сохраняются ли большие буферы в глобальном состоянии;
  • не растет ли очередь задач быстрее, чем consumer успевает обрабатывать.

Для Go полезны также pprof и runtime metrics, но базовое наблюдение через ps, top и контейнерные метрики уже помогает увидеть направление проблемы.

Сигналы

Сигналы позволяют завершать или управлять процессом:

kill -TERM <pid> kill -INT <pid> kill -KILL <pid>

SIGTERM просит завершиться корректно. SIGINT обычно приходит от Ctrl+C. SIGKILL убивает процесс сразу и не дает ему закрыть файлы или соединения.

В Go сигнал можно обработать через os/signal:

ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() <-ctx.Done()

Это основа graceful shutdown: сервис получает сигнал, перестает принимать новые запросы и дает текущим операциям время завершиться.

Файловые дескрипторы

Открытые файлы, сокеты и pipes - это файловые дескрипторы:

ls /proc/<pid>/fd

Если программа не закрывает файлы или сетевые соединения, количество дескрипторов растет. В какой-то момент процесс может получить ошибку "too many open files".

В Go частая ошибка:

resp, err := http.Get(url) if err != nil { return err } // забыли resp.Body.Close()

Правильно:

defer resp.Body.Close()

Порты и соединения

Если backend не запускается, потому что порт занят, полезны команды:

lsof -i :8080 ss -lntp

Они помогают понять, какой процесс слушает порт.

Для сетевых сервисов смотрите не только CPU и память, но и количество соединений. Медленные клиенты или зависшие запросы могут держать соединения открытыми слишком долго.

Диагностика Go-программы

Когда сервис ведет себя странно, задайте базовые вопросы:

  1. Процесс вообще жив?
  2. Какой у него PID?
  3. Сколько памяти занимает RSS?
  4. Растет ли RSS со временем?
  5. Сколько файловых дескрипторов открыто?
  6. Слушает ли процесс нужный порт?
  7. Обрабатывает ли сервис SIGTERM?
  8. Есть ли в логах старт, остановка и критичные ошибки?

Эти вопросы часто быстрее приводят к причине, чем чтение кода с первой строки.

Контейнеры

В Docker и Kubernetes процесс все равно остается Linux-процессом. Просто он работает в изолированном окружении с лимитами.

Если контейнер убит из-за памяти, в Kubernetes можно увидеть OOMKilled. Это значит, что процесс превысил memory limit.

Для локальной диагностики:

docker stats docker compose logs api docker compose exec api sh

Чеклист

  1. Для долгих сервисов реализован graceful shutdown.
  2. Файлы и сетевые соединения закрываются.
  3. Память проверяется по RSS и available.
  4. Рост RSS во времени расследуется отдельно.
  5. Количество файловых дескрипторов не растет бесконечно.
  6. SIGKILL используется только как крайняя мера.
  7. Логи показывают старт, остановку и критичные ошибки.
  8. Для занятого порта проверяется процесс-владелец.

Следующий шаг после статьи

Закрепите тему в реальном проекте и продолжайте обучение на курсах Praxis.

Продолжить изучение

Выбери следующую статью по маршруту или углубись в смежную тему.

Предыдущая статья
Интеграции с внешними API в Go
Ты дошел до последней статьи в маршруте.

Похожие статьи