Linux OOMВысокая

OOM Killer в Linux: причины и способы решения ошибки нехватки памяти

Статья объясняет, что такое OOM Killer (Out of Memory Killer), почему ядро Linux принудительно завершает процессы и как это исправить. Вы научитесь диагностировать нехватку памяти и настроить систему для стабильной работы.

Обновлено 8 апреля 2026 г.
15-30 мин
Средняя
FixPedia Team
Применимо к:Linux ядра 3.x и вышеВсе дистрибутивы (Ubuntu, CentOS, Debian, RHEL)

Что означает ошибка OOM

OOM Killer (Out-of-Memory Killer) — это механизм ядра Linux, который автоматически завершает один или несколько процессов, когда система исчерпала доступную оперативную память (RAM) и swap-пространство. Это не ошибка приложения, а реакция ядра на критическую нехватку памяти, чтобы избежать полного зависания системы.

Типичный вывод в логах (dmesg):

[12345.678901] Out of memory: Kill process 1234 (some-process) score 999 or sacrifice child
[12345.678912] Killed process 1234 (some-process) total-vm:123456kB, anon-rss:98765kB, file-rss:1234kB

Симптомы у пользователя: неожиданное падение сервисов (например, PostgreSQL, Java-приложение, веб-сервер), сообщения Killed в терминале при запуске программ, невозможность создать новые процессы.

Причины возникновения

  1. Физическая нехватка RAM + swap. Запущенные процессы потребляют больше памяти, чем доступно физически + в swap. Часто происходит из-за утечек памяти (memory leaks) в долгоживущих приложениях.
  2. Агрессивный overcommit. Ядро Linux по умолчанию разрешает выделение памяти, которой физически нет (overcommit), полагаясь на то, что приложения её не используют полностью. Если же все процессы решат использовать зарезервированное — OOM Killer сработает.
  3. Конфигурация swap слишком мала или отсутствует. На системах без swap или с минимальным swap (например, 1-2 ГБ) OOM Killer срабатывает при меньшей нагрузке, так как нет буфера для выгрузки неактивных страниц.
  4. Злонамеренный или buggy процесс. Процесс может намеренно выделять память (например, fork-бомба) или содержать баг, приводящий к бесконечному росту потребления памяти.
  5. Недостаток cgroup-лимитов. В контейнерах (Docker) или виртуальных средах, где память ограничена через cgroups, OOM Killer может убить процесс внутри контейнера, даже если на хосте ещё есть свободная память.

Способы решения

Способ 1: Быстрая диагностика и освобождение памяти

Первым делом определите, какой процесс виновник и сколько памяти свободно.

  1. Проверьте общую статистику:
    free -h
    

    Обратите внимание на строку available — это реально доступная память для новых процессов. Если значение близко к нулю — проблема серьёзная.
  2. Найдите "тяжёлых" процессов:
    ps aux --sort=-%mem | head -10
    

    Это покажет топ-10 процессов по потреблению RAM.
  3. Проверьте, нет ли процессов с аномально высоким VIRT (виртуальная память), но низким RES (физическая) — возможна overcommit-атака.
  4. Если система ещё реагирует, попробуйте вручную завершить не критичный процесс с высоким потреблением:
    sudo kill -9 <PID>
    

    Используйте с осторожностью, только если уверены в природе процесса.

Способ 2: Добавление или увеличение swap-файла

Если у вас мало swap (например, менее размера RAM), создайте дополнительный swap-файл. Это даст ядру больше "воздуха".

  1. Создайте файл размером 4 ГБ (подберите размер под нагрузку):
    sudo fallocate -l 4G /swapfile
    

    Если fallocate недоступен, используйте dd if=/dev/zero of=/swapfile bs=1M count=4096.
  2. Установите правильные права и подготовьте как swap:
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    
  3. Активируйте swap:
    sudo swapon /swapfile
    
  4. Чтобы swap включался автоматически при загрузке, добавьте строку в /etc/fstab:
    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
    
  5. Проверьте:
    swapon --show
    free -h
    

⚠️ Важно: Swap на SSD ускорит работу, но увеличит износ. Для серверов с большим RAM (16+ ГБ) swap может быть минимальным (2-4 ГБ) или отключённым, но тогда OOM Killer сработает быстрее.

Способ 3: Настройка OOM-политики для конкретных процессов

Иногда нужно защитить критичный сервис (например, базу данных) от убийства, пожертвовав менее важным.

Для системd-сервисов (современные дистрибутивы)

Создайте override-конфигурацию для сервиса:

sudo systemctl edit <имя_сервиса>

В открывшемся редакторе добавьте:

[Service]
OOMScoreAdjust=-900

Значение -1000 — абсолютная защита (ядро не будет убивать такой процесс даже при тотальном OOM). -900 — очень низкий приоритет на убийство. Сохраните и перезапустите сервис:

sudo systemctl daemon-reload
sudo systemctl restart <имя_сервиса>

Для ручных процессов

Запустите процесс с изменённым OOM-скорингом через systemd-run (если система использует systemd):

systemd-run --scope -p OOMScoreAdjust=-500 ./ваша_программа

Или через prctl в коде (для разработчиков). Для уже запущенного процесса изменить oom_score_adj можно:

echo -1000 | sudo tee /proc/<PID>/oom_score_adj

Требует прав root, изменение временное (до перезапуска процесса).

Способ 4: Тюнинг ядра — overcommit и watermark

Эти настройки глобальные и требуют понимания. Редактируйте /etc/sysctl.conf или создайте файл в /etc/sysctl.d/.

  1. Уменьшите агрессивность overcommit (по умолчанию 0 — heuristic overcommit, 1 — всегда overcommit, 2 — строгий режим):
    sudo sysctl -w vm.overcommit_memory=2
    sudo sysctl -w vm.overcommit_ratio=80  # Разрешить выделять не более 80% RAM+swap
    

    В режиме 2 ядро будет отклонять запросы на malloc(), если не хватит памяти, что предотвратит OOM, но может сломать некоторые приложения, ожидающие overcommit.
  2. Настройте watermark'ы — пороги, при которых ядро начинает активный OOM Killer:
    sudo sysctl -w vm.min_free_kbytes=65536  # Минимальный резерв свободной памяти (в КБ). Увеличьте, если OOM срабатывает при наличии памяти.
    

    Будьте осторожны: слишком высокое значение может привести к неэффективному использованию памяти.
  3. Внесите изменения постоянно:
    echo "vm.overcommit_memory=2" | sudo tee -a /etc/sysctl.conf
    echo "vm.overcommit_ratio=80" | sudo tee -a /etc/sysctl.conf
    

Способ 5: Анализ и исправление утечек памяти

Если OOM Killer периодически убивает один и тот же процесс (например, java или python), вероятна утечка.

  1. Мониторинг в реальном времени:
    watch -n 1 'ps aux --sort=-%mem | head -5'
    
  2. Для Java-приложений используйте jcmd или jmap для анализа heap:
    jcmd <PID> GC.heap_info
    jmap -dump:live,format=b,file=heap.hprof <PID>
    

    Затем проанализируйте дамп через MAT (Memory Analyzer Tool).
  3. Для процессов на C/C++ используйте valgrind --tool=memcheck при тестировании, или pmap -x <PID> для просмотра детального распределения памяти.
  4. Проверьте логи приложения на предмет ошибок, связанных с памятью (например, OutOfMemoryError в Java).

Профилактика

  • Регулярный мониторинг. Настройте алерты (через Prometheus+Grafana, Zabbix, Netdata) на ключевые метрики: mem.available, vmstat.si/so, oom_kill (счётчик в /proc/vmstat).
  • Адекватный swap. Размер swap рекомендуется как минимум равен размеру RAM для настольных систем, для серверов — от 1/2 до 1× RAM в зависимости от нагрузки.
  • Ограничение ресурсов через cgroups. Для контейнеров и сервисов явно задавайте лимиты памяти (memory.limit_in_bytes в Docker или MemoryMax в systemd), чтобы OOM Killer срабатывал внутри изолированной группы, а не на всём хосте.
  • Обновление ПО. Утечки памяти часто исправляются в обновлениях. Следите за changelog критичных приложений (базы данных, веб-серверы, виртуализация).
  • Настройка oom_score_adj для важных сервисов. Как показано в Способе 3, защитите ключевые процессы от автоматического убийства.
  • Планирование нагрузки. Зная пиковые нагрузки, рассчитайте необходимый объём RAM + swap. Используйте stress-ng или memtester для тестирования стабильности под давлением.

Часто задаваемые вопросы

Почему Linux убивает мои процессы при наличии свободной памяти?
Как узнать, какой процесс был убит OOM?
Можно ли полностью отключить OOM Killer?
Чем OOM Killer отличается от swap?

Полезное

Диагностика: проверьте использование памяти иswap
Найдите процесс-жертву в системных логах
Временно увеличьте swap-пространство
Настройте overcommit и политику OOM для конкретного сервиса
Оптимизируйте приложение или добавьте физической памяти