Что делать если начал расти swap: шпаргалка IT-инженера с примерами

Системный администратор Linux (Ubuntu) за работой. Читает документацию в консоли.

Сервер тормозит. Смотришь мониторинг — swap жрёт уже 80%. RAM вроде есть, но система выгружает всё в swap и превращается в тыкву. Знакомо?

Эта шпаргалка — для тех, кто хочет быстро разобраться, почему swap растёт, что с этим делать и как не допустить в следующий раз. Без теории про виртуальную память — только команды, которые работают.

Когда это использовать

Реальные кейсы:

  • Сервер начал тупить, а в мониторинге видно, что swap занят на 50%+
  • MySQL/PostgreSQL начали работать медленнее после обновления
  • После деплоя приложение стало отвечать по 10 секунд
  • Backup-скрипт запустился и положил production
  • Elasticsearch начал жрать swap и умер

Типовые ситуации:

  • Утечка памяти в приложении
  • Неправильная настройка swappiness
  • Слишком много сервисов на одной машине
  • Кто-то забыл отключить swap для базы данных
  • Memory leak в Java/Node.js приложении

Ошибки новичков:

  • Думают, что swap — это нормально («у меня же 32GB swap!»)
  • Отключают swap совсем, а потом OOM Killer убивает процессы
  • Не смотрят, ЧТО именно в swap
  • Перезагружают сервер вместо того, чтобы найти причину

Быстрый старт (если горит прод)

1. Смотрим ситуацию:

free -h
swapon --show

2. Находим, кто жрёт swap:

for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | head

3. Убиваем процесс (если нашли виновника):

kill -9 PID

4. Очищаем swap (если RAM позволяет):

swapoff -a && swapon -a

5. Смотрим логи убитого процесса, чтобы понять WTF:

journalctl -u service_name --since "10 minutes ago"

Основные команды и приёмы

Посмотреть состояние swap

Самая базовая команда — увидеть, сколько swap используется.

free -h

Вывод:

              total        used        free      shared  buff/cache   available
Mem:           15Gi       8.0Gi       1.2Gi       234Mi       6.1Gi       6.8Gi
Swap:         2.0Gi       1.8Gi       200Mi

Если used у Swap больше 50% — пора разбираться.

Узнать, где лежит swap

Swap может быть на разделе или в файле. Важно знать, где именно.

swapon --show
NAME      TYPE      SIZE   USED PRIO
/swapfile file        2G   1.8G   -2

Найти процессы, которые используют swap

Главная команда шпаргалки. Показывает, кто именно сидит в swap.

for file in /proc/*/status ; do awk '/VmSwap|Name/{printf $2 " " $3}END{ print ""}' $file; done | sort -k 2 -n -r | head -20

Вывод:

java 1843200 kB
mysqld 654320 kB
node 123456 kB

Эта команда спасала прод чаще, чем бэкапы.

Найти PID процесса по имени

Если знаешь имя процесса, а PID нужен для kill.

ps aux | grep java | grep -v grep

Или проще:

pgrep -a java

Посмотреть swap конкретного процесса

Если знаешь PID и хочешь увидеть детали.

cat /proc/PID/status | grep -i swap

Или сразу по имени:

ps aux | grep <a class="wpil_keyword_link" href="https://it-apteka.com/tag/mysql/"   title="MySQL" data-wpil-keyword-link="linked"  data-wpil-monitor-id="240">mysql</a> | awk &#039;{print $2}&#039; | xargs -I {} cat /proc/{}/status | grep -i swap

Посмотреть swappiness

Swappiness — агрессивность ядра по выгрузке в swap. От 0 до 100.

cat /proc/sys/vm/swappiness

Значения:

  • 0 — swap только в крайнем случае (для баз данных)
  • 10 — минимальное использование swap (рекомендуется для серверов)
  • 60 — дефолт в Ubuntu/Debian (слишком много для прода)
  • 100 — максимальная агрессивность (никогда не ставьте)

Изменить swappiness (временно)

Применится сразу, но после перезагрузки сбросится.

sysctl vm.swappiness=10

Изменить swappiness (навсегда)

Добавить в конфиг, чтобы настройка пережила reboot.

echo "vm.swappiness=10" >> /etc/sysctl.conf
sysctl -p

Очистить swap (вернуть всё в RAM)

Внимание: команда вернёт все данные из swap в RAM. Если RAM не хватит — OOM Killer начнёт убивать процессы.

Сначала проверь, что свободной RAM хватит:

free -h

Если available RAM больше, чем used swap — можно чистить:

swapoff -a && swapon -a

Эта команда:

  • Отключает swap (всё перегружается в RAM)
  • Включает swap обратно (он теперь пустой)

Отключить swap совсем

Иногда нужно для баз данных (MySQL, PostgreSQL, Elasticsearch).

swapoff -a

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

sed -i '/swap/d' /etc/fstab

Важно: отключать swap имеет смысл только если RAM реально хватает с запасом. Иначе OOM Killer начнёт убивать процессы при нехватке памяти.

Включить swap обратно

Если передумал отключать или нужно для тестов.

swapon -a

Создать swap-файл (если его нет)

Быстрый способ добавить swap на сервер.

# Создаём файл на 4GB
fallocate -l 4G /swapfile

# Права доступа
chmod 600 /swapfile

# Форматируем в swap
mkswap /swapfile

# Включаем
swapon /swapfile

# Добавляем в fstab, чтобы заработало после перезагрузки
echo '/swapfile none swap sw 0 0' >> /etc/fstab

Удалить swap-файл

Если swap больше не нужен.

swapoff /swapfile
rm /swapfile
sed -i '/swapfile/d' /etc/fstab

Посмотреть историю использования swap (если есть atop)

Atop сохраняет историю. Можно посмотреть, когда началось.

atop -r /var/log/atop/atop_20240202 -M

Нажми m для сортировки по памяти.

Посмотреть топ процессов по RAM

Кто жрёт память прямо сейчас.

ps aux --sort=-%mem | head -20

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

top

Нажми M (shift+m) для сортировки по памяти.

Найти утечку памяти в Java

Если Java-приложение жрёт всю память и swap.

# Найти PID Java-процесса
jps -l

# Dump heap
jmap -dump:live,format=b,file=heap.bin PID

# Анализировать с помощью Eclipse MAT или VisualVM

Найти утечку памяти в Node.js

Если Node.js процесс раздулся.

# Включить инспектор
node --inspect app.js

# Открыть Chrome DevTools
# chrome://inspect

# Сделать heap snapshot

Или через сторонние инструменты:

npm install -g clinic
clinic doctor -- node app.js

Ограничить память для процесса (systemd)

Если сервис регулярно жрёт всю память — ограничь его.

# Редактируем unit файл
systemctl edit service_name

Добавляем:

[Service]
MemoryMax=2G
MemoryHigh=1.5G

Перезагружаем:

systemctl daemon-reload
systemctl restart service_name

Ограничить память для Docker-контейнера

Docker может жрать весь swap. Ограничь контейнер.

docker run -m 512m --memory-swap 512m your_image

Или в docker-compose.yml:

services:
  app:
    image: your_image
    mem_limit: 512m
    memswap_limit: 512m

Посмотреть swap в htop

Если htop установлен — он показывает swap удобнее.

htop

Нажми F6 → выбери SWAP для сортировки.

Частые ошибки и подводные камни

«У меня 32GB RAM, но система использует swap» — WTF?

Причина: высокий swappiness. Ядро агрессивно выгружает редко используемые страницы в swap, освобождая RAM под cache.

Решение:

echo "vm.swappiness=10" >> /etc/sysctl.conf
sysctl -p
swapoff -a && swapon -a

«Я очистил swap, но он опять вырос через 10 минут»

Причина: утечка памяти в приложении или процесс реально жрёт больше, чем есть RAM.

Решение:
Найди процесс, который растёт, и разберись с утечкой. Временная чистка swap — не решение проблемы.

watch -n 5 'ps aux --sort=-%mem | head -20'

«Отключил swap, теперь OOM Killer убивает MySQL»

Причина: RAM не хватает, а swap выключен. OOM Killer начинает убивать процессы.

Решение:
Либо добавь RAM, либо верни swap обратно, либо ограничь память другим процессам.

swapon -a

«Сервер тормозит, хотя swap используется только на 20%»

Причина: swap на HDD, а не на SSD. Любое обращение к swap на HDD — это тормоза.

Решение:
Перенеси swap на SSD или уменьши swappiness до минимума.

sysctl vm.swappiness=1

«PostgreSQL тупит, хотя RAM полно»

Причина: PostgreSQL или другая БД попала в swap. Базы данных и swap — несовместимы.

Решение:
Отключи swap для сервера с базой данных.

swapoff -a
sed -i '/swap/d' /etc/fstab

Или настрой swappiness=0:

echo "vm.swappiness=0" >> /etc/sysctl.conf
sysctl -p

«Не могу очистить swap, команда swapoff -a зависает»

Причина: не хватает свободной RAM, чтобы вернуть данные из swap.

Решение:
Останови ненужные сервисы, освободи RAM, потом очищай swap.

systemctl stop apache2
systemctl stop some_heavy_service
swapoff -a && swapon -a
systemctl start apache2
systemctl start some_heavy_service

«Swap растёт только ночью во время backup»

Причина: backup-скрипт жрёт много памяти (например, tar, mysqldump, pg_dump).

Решение:
Ограничь память для backup-процесса или запускай его с nice/ionice.

nice -n 19 ionice -c3 tar czf backup.tar.gz /data

Полезные хаки

Алиас для быстрой проверки swap

Добавь в ~/.bashrc или ~/.zshrc:

alias swapcheck='for file in /proc/*/status ; do awk '"'"'/VmSwap|Name/{printf $2 " " $3}END{ print ""}'"'"' $file; done | sort -k 2 -n -r | head -20'

Теперь просто:

swapcheck

Мониторинг swap в реальном времени

Смотреть, как меняется swap каждые 2 секунды:

watch -n 2 free -h

Логирование процессов, которые попадают в swap

Скрипт, который логирует процессы с swap > 100MB:

#!/bin/bash
while true; do
  for pid in /proc/[0-9]*; do
    swap=$(grep VmSwap $pid/status 2>/dev/null | awk '{print $2}')
    if [ "$swap" -gt 102400 ]; then
      name=$(grep Name $pid/status | awk '{print $2}')
      echo "$(date): $name (PID: $(basename $pid)) using $swap kB swap" >> /var/log/swap_monitor.log
    fi
  done
  sleep 60
done

Запусти в screen/tmux или через systemd.

Автоматическая чистка swap при превышении порога

Если swap больше 80% — очищаем автоматически (используй осторожно):

#!/bin/bash
SWAP_USAGE=$(free | grep Swap | awk '{print ($3/$2)*100}')
if (( $(echo "$SWAP_USAGE > 80" | bc -l) )); then
  echo "Swap usage is $SWAP_USAGE%. Clearing swap..."
  swapoff -a && swapon -a
fi

Добавь в cron:

*/10 * * * * /root/clear_swap.sh

Отключить swap только для конкретного процесса

Невозможно через стандартные средства Linux, но можно использовать cgroups v2:

# Создать cgroup
mkdir /sys/fs/cgroup/no_swap
echo 0 > /sys/fs/cgroup/no_swap/memory.swap.max

# Добавить процесс в cgroup
echo PID > /sys/fs/cgroup/no_swap/cgroup.procs

Флаг —si для человекочитаемого вывода

Вместо kB, MB, GB — показывает в степенях 1000, а не 1024:

free --si

Полезно для отчётов, где нужны «круглые» цифры.

Использовать tmpfs вместо swap для временных файлов

Если приложение создаёт много временных файлов — используй tmpfs (RAM).

mount -t tmpfs -o size=2G tmpfs /tmp/app_cache

Добавить в /etc/fstab:

tmpfs /tmp/app_cache tmpfs size=2G 0 0

Сжатие swap (zswap)

Включить сжатие swap в памяти (помогает продлить жизнь при нехватке RAM):

echo 1 > /sys/module/zswap/parameters/enabled

Для постоянного включения добавь в /etc/default/grub:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash zswap.enabled=1"

Обнови grub:

update-grub
reboot

Проверка и диагностика

Убедиться, что swap работает

swapon --show
free -h

Если swap не отображается — значит не включен.

Проверить, что swappiness применился

cat /proc/sys/vm/swappiness

Должно быть 10 (или то значение, которое ты установил).

Посмотреть логи OOM Killer

Если процессы убиваются из-за нехватки памяти:

dmesg | grep -i oom
journalctl -k | grep -i oom

Проверить, что процесс не в swap

cat /proc/PID/status | grep VmSwap

Если VmSwap = 0 kB — процесс не использует swap.

Проверить скорость диска для swap

Если swap на медленном диске — это причина тормозов:

hdparm -t /dev/sda

Для SSD:

fio --name=swap_test --rw=randrw --bs=4k --size=1G --numjobs=4 --runtime=60 --group_reporting

Если скорость < 100 MB/s — swap на HDD, нужно переносить на SSD.

Посмотреть приоритет swap

Если несколько swap-разделов — можно посмотреть приоритеты:

swapon --show

Приоритет (PRIO) определяет, какой swap использовать первым. Чем выше число — тем выше приоритет.

Изменить приоритет swap

swapon --priority 10 /swapfile

Краткий чек-лист

Что должно быть сделано:

  • Swappiness установлен на 10 для серверов (или 0 для баз данных)
  • Swap на SSD, а не на HDD
  • Размер swap = 1x-2x RAM (или меньше, если RAM > 16GB)
  • Мониторинг swap настроен (Prometheus, Zabbix, Grafana)
  • Лимиты памяти для сервисов (systemd, Docker)

Что проверить перед продом:

  • Swap не используется при нормальной нагрузке
  • Swappiness = 10
  • OOM Killer не срабатывал последние 30 дней
  • Нет утечек памяти в приложениях
  • Базы данных НЕ используют swap

Что сохранить себе:

  • Алиас для swapcheck
  • Команду для поиска процессов в swap
  • Скрипт мониторинга swap
  • Настройки swappiness в /etc/sysctl.conf

Резюме

Swap — не зло, но и не решение. Если swap растёт — ищи причину, а не просто чисти его каждые 10 минут.

Сохрани эту шпаргалку в закладки. В следующий раз, когда прод начнёт тупить из-за swap, ты будешь знать, что делать.

Следующая шпаргалка: «Как найти утечку памяти в production за 5 минут».

Поделитесь:

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх