Сервер тормозит. Смотришь мониторинг — 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 '{print $2}' | 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 минут».




