3 часа ночи. Мониторинг орёт. Memory usage 95%. OOM killer начал убивать процессы. Босс в личке спрашивает ETA. Знакомо?
Эта шпаргалка — для тех, кто не хочет гуглить базовые команды, пока сервер умирает. Здесь только рабочие команды, которые можно скопировать и запустить прямо сейчас.
Время на диагностику: 5 минут. Время на фикс зависит от вашего кода (и от того, насколько сильно вы наследовали от легаси).
Когда это использовать
Реальные кейсы:
- RAM растёт, не падает даже после рестарта трафика
- Приложение медленно жрёт память и через N часов падает
- После деплоя новой версии сервер начал пухнуть
- Kubernetes постоянно перезапускает поды из-за OOM
- Swap забит, система тормозит как Windows Vista
Типовые ошибки новичков:
- Смотрят только на free -h (и не понимают, что cache != leak)
- Рестартят сервис вместо поиска причины
- Не снимают heap dump до рестарта (и теряют все улики)
- Путают memory leak с нормальным ростом кеша
Быстрый старт (если горит прям сейчас)
1. Найдите процесс-жрун:
ps aux --sort=-%mem | head -10
2. Проверьте динамику:
watch -n 1 'ps aux --sort=-%mem | head -5'
3. Снимите heap dump (для Java/Node.js/Python):
# Java jmap -dump:live,format=b,file=/tmp/heap_dump.hprof <PID> # Node.js kill -USR2 <PID> # если настроен heapdump модуль # Python py-spy dump --pid <PID> > /tmp/stack_trace.txt
4. Освободите память экстренно (если уже OOM):
sync && echo 3 > /proc/sys/vm/drop_caches
5. Рестартните сервис (после снятия дампа!):
systemctl restart your-app
Дальше — разбор дампа на dev-окружении. Не в проде. Пожалуйста.
Основные команды для диагностики
1. Общая картина памяти
Смотрим, что вообще происходит с памятью в системе.
free -h
Что смотреть:
- available — реально доступная память (не total — used!)
- buff/cache — это нормально, kernel использует свободную память
- swap used — если >0, уже плохо
Если available < 10% от total — у вас проблема.
2. Поиск процесса-виновника
Самый жирный процесс по памяти:
ps aux --sort=-%mem | head -20
Или в реальном времени (обновление каждую секунду):
watch -n 1 'ps aux --sort=-%mem | head -10'
Если нужен топ с визуализацией — используйте htop:
htop # Нажмите F6 -> выберите PERCENT_MEM -> Enter
3. Смотрим динамику роста памяти
Логируем потребление памяти конкретным процессом каждые 5 секунд:
PID=12345 # замените на реальный PID while true; do ps -p $PID -o %mem,rss,vsz,cmd | tail -1 sleep 5 done
Если RSS (Resident Set Size) растёт линейно — у вас leak. Если скачет — это cache или нормальная работа GC.
4. Проверка memory maps процесса
Смотрим, куда утекает память внутри процесса:
pmap -x <PID> | sort -nrk3 | head -20
Или более детально:
cat /proc/<PID>/smaps | grep -A 15 "^Size" | head -50
Что искать: большие анонимные регионы (anon), которые растут.
5. Проверка открытых файлов (частая причина leak)
Приложение может жрать память через незакрытые файловые дескрипторы:
lsof -p <PID> | wc -l
Если число дескрипторов растёт — у вас file descriptor leak (который тоже ест память).
Детальный список:
lsof -p <PID> | grep -i mem
6. Heap dump для разных языков
Java (JVM)
Снять heap dump без остановки приложения:
jmap -dump:live,format=b,file=/tmp/heap.hprof <PID>
Быстрый анализ прямо в консоли:
jmap -histo:live <PID> | head -30
Если jmap не работает (бывает на production):
kill -3 <PID> # Thread dump в stdout/логи
Node.js
Установите heapdump модуль заранее:
npm install heapdump
В коде приложения:
const heapdump = require('heapdump');
// Сигнал для снятия дампа
process.on('SIGUSR2', () => {
heapdump.writeSnapshot((err, filename) => {
console.log('Heap dump:', filename);
});
});
Снять dump:
kill -USR2 <PID>
Альтернатива — использовать node —inspect и Chrome DevTools.
Python
Быстрый snapshot через py-spy (не требует изменений в коде):
pip install py-spy py-spy dump --pid <PID>
Для детального анализа — tracemalloc (нужно добавить в код):
import tracemalloc
tracemalloc.start()
# ваш код
snapshot = tracemalloc.take_snapshot()
top_stats = snapshot.statistics('lineno')
for stat in top_stats[:10]:
print(stat)
Go
Если в приложении включён pprof:
curl http://localhost:6060/debug/pprof/heap > heap.prof go tool pprof -http=:8080 heap.prof
7. Анализ через valgrind (для C/C++)
Если у вас нативное приложение:
valgrind --leak-check=full --log-file=valgrind.log ./your_app
Внимание: valgrind замедляет приложение в 10-50 раз. Используйте только на dev/staging.
8. Системный мониторинг в реальном времени
Если нужно следить за несколькими процессами:
top -b -n 1 | grep -E "(java|node|python|your_app)"
Или более продвинутый вариант с glances:
pip install glances glances
Glances показывает всё: CPU, RAM, I/O, network — в одном экране.
Частые ошибки и подводные камни
1. «Памяти нет, но free показывает много»
Проблема: Смотрят на «free» вместо «available».
Решение:
free -h # Смотрите на строку "available", а не "free"
Cache и buffers — это не утечка. Это нормальная работа kernel.
2. «Рестартнул сервис — памяти не прибавилось»
Проблема: Память не возвращается в систему сразу после kill процесса.
Решение: Принудительно очистите cache:
sync && echo 3 > /proc/sys/vm/drop_caches
Или просто подождите 30-60 секунд — kernel сам освободит.
3. «PID меняется после рестарта, скрипты ломаются»
Проблема: Хардкодят PID в скриптах мониторинга.
Решение: Используйте pidof или systemctl:
PID=$(pidof your-app) # или PID=$(systemctl show --property MainPID --value your-app)
4. «Heap dump весит 10GB, сервер умер»
Проблема: Снимают dump на проде с полным heap.
Решение: Используйте live объекты:
jmap -dump:live,format=b,file=/tmp/heap.hprof <PID>
Флаг live запускает GC перед дампом и сохраняет только живые объекты.
5. «Memory leak только на production»
Проблема: На dev окружении нагрузка в 100 раз меньше.
Решение: Используйте staging с реальным объёмом трафика. Или нагрузочное тестирование:
# Apache Bench ab -n 100000 -c 100 http://your-app/endpoint # wrk (более продвинутый) wrk -t12 -c400 -d30s http://your-app/endpoint
Leak проявится быстрее.
Полезные хаки
1. Алиас для быстрого поиска жирных процессов
Добавьте в ~/.bashrc:
alias memtop='ps aux --sort=-%mem | head -20' alias memwatch='watch -n 1 "ps aux --sort=-%mem | head -10"'
Теперь просто пишете memtop — и всё перед глазами.
2. Логирование памяти в файл
Скрипт для автоматического мониторинга:
#!/bin/bash LOG_FILE="/var/log/memory_monitor.log" PID=$(pidof your-app) while true; do TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S') MEM=$(ps -p $PID -o %mem,rss | tail -1) echo "$TIMESTAMP - $MEM" >> $LOG_FILE sleep 60 done
Запустите в screen/tmux:
screen -dmS memlog <a class="wpil_keyword_link" href="https://it-apteka.com/tag/bash/" title="Bash" data-wpil-keyword-link="linked" data-wpil-monitor-id="226">bash</a> /path/to/monitor.sh
3. Уведомление в Slack при превышении лимита
#!/bin/bash
THRESHOLD=80 # процент памяти
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK"
MEM_USAGE=$(free | grep Mem | awk '{print int($3/$2 * 100)}')
if [ $MEM_USAGE -gt $THRESHOLD ]; then
curl -X POST -H 'Content-type: application/json' \
--data "{\"text\":\"⚠️ Memory usage: ${MEM_USAGE}%\"}" \
$WEBHOOK_URL
fi
Добавьте в cron на запуск каждые 5 минут:
*/5 * * * * /path/to/mem_alert.sh
4. Быстрый анализ Java heap dump без GUI
Если нет доступа к Eclipse MAT:
# Установите jhat (входит в JDK) jhat -J-Xmx4G /tmp/heap.hprof # Откройте в браузере # http://localhost:7000
Или используйте консольный анализатор:
jmap -histo /tmp/heap.hprof | head -50
5. Ограничение памяти через systemd
Чтобы процесс не сожрал весь сервер:
# /etc/systemd/system/your-app.service [Service] MemoryLimit=2G MemoryMax=2G
Перезагрузите конфиг:
systemctl daemon-reload systemctl restart your-app
Теперь при превышении 2GB процесс будет убит OOM killer.
6. cgroup для изоляции памяти
Если systemd нет или нужен более гибкий контроль:
# Создаём cgroup cgcreate -g memory:/myapp # Лимит 2GB echo 2147483648 > /sys/fs/cgroup/memory/myapp/memory.limit_in_bytes # Запускаем процесс в cgroup cgexec -g memory:/myapp /path/to/your-app
Проверка и диагностика
Чек-лист перед завершением диагностики
1. Подтвердите leak (а не нормальный рост):
# Запустите <a class="wpil_keyword_link" title="Мониторинг" href="https://it-apteka.com/category/monitoring/" data-wpil-keyword-link="linked" data-wpil-monitor-id="212">мониторинг</a> на 10 минут watch -n 10 'ps aux --sort=-%mem | head -5'
Если RSS растёт линейно без падений — это leak.
2. Проверьте логи приложения:
tail -f /var/log/your-app/error.log | grep -i "memory\|oom\|allocation"
3. Проверьте system logs:
dmesg | grep -i "out of memory\|oom" journalctl -xe | grep -i oom
Если видите «Out of memory: Killed process» — kernel уже начал убивать процессы.
4. Сохраните все дампы и логи:
mkdir -p /var/backups/memory_incident_$(date +%Y%m%d_%H%M%S) cp /tmp/*.hprof /tmp/*.prof /var/log/your-app/* /var/backups/memory_incident_*/
5. Задокументируйте инцидент:
- Когда началось
- Какой процесс
- Сколько памяти жрало
- Что изменилось перед этим (деплой, конфиг, трафик)
- Что помогло (рестарт, патч, откат)
Где смотреть логи
System logs:
# OOM events dmesg -T | grep -i oom # Systemd journal journalctl -u your-app --since "1 hour ago" # Kernel logs tail -f /var/log/kern.log
Application logs:
# Стандартные локации /var/log/your-app/ ~/.pm2/logs/ # для Node.js с PM2 /var/log/nginx/error.log # если leak в nginx
Краткий чек-лист
Что должно быть сделано:
- ✅ Найден процесс с утечкой (ps aux —sort=-%mem)
- ✅ Подтверждена динамика роста (watch на 5-10 минут)
- ✅ Снят heap dump ДО рестарта
- ✅ Проверены логи на OOM events
- ✅ Сохранены все дампы и метрики
Что проверить перед продом:
- ✅ Нагрузочное тестирование с мониторингом памяти
- ✅ Настроены алерты на memory usage >80%
- ✅ Включён автоматический heap dump при OOM (для Java)
- ✅ Ограничения памяти через systemd/cgroup
- ✅ Логирование метрик памяти в monitoring (Prometheus/Grafana)
Что сохранить себе:
- Скрипты мониторинга памяти
- Алиасы для быстрой диагностики
- Команды для heap dump вашего стека
- Ссылку на эту шпаргалку
Резюме
Утечка памяти в production — это не катастрофа, если знаешь, что делать. Главное:
- Быстро найти виновника (ps aux —sort=-%mem)
- Снять heap dump до рестарта (иначе потеряете улики)
- Не паниковать (cache != leak)
- Автоматизировать мониторинг (чтобы в следующий раз проснуться раньше OOM killer)
Эта шпаргалка спасала прод чаще, чем бэкапы. Добавьте её в закладки — она вам ещё пригодится. Обычно в 3 часа ночи.
В следующей шпаргалке разберём как найти CPU bottleneck за 5 минут. Потому что после memory leak обычно начинаются проблемы с процессором.



