Cannot allocate memory в журнале службы
Сообщение Cannot allocate memory (номер 12, ENOMEM) означает отказ выделения памяти. У служб под systemd причины три: собственный предел памяти, нехватка памяти на машине и системные ограничения вроде числа областей отображения.
Вероятные причины
По порядку: сверху то, что встречается чаще.
-
Упор в предел памяти службы
При заданном
MemoryMax=выделение сверх предела не проходит. Если программа обрабатывает отказ, она сообщает об ошибке вместо смерти. -
Кончилась память на машине
При исчерпании памяти и отсутствии подкачки выделение падает у всех процессов.
-
Исчерпаны области отображения памяти
Предел
vm.max_map_countограничивает число областей на процесс. Службы вроде Elasticsearch упираются в него при значении по умолчанию.
Диагностика
Команды идут в том порядке, в котором их стоит выполнять: каждая следующая проверяет то, что осталось после предыдущей.
Память машины и пределы службы вместе.
free -h && systemctl show myapp.service -p MemoryMax -p MemoryPeakРаботал ли механизм освобождения памяти.
journalctl -k -b --no-pager | grep -iE "out of memory|oom"Системные настройки, влияющие на выделение.
sysctl vm.overcommit_memory vm.max_map_countРешение
Решение своё для каждой причины. Сначала определите, какая из них ваша, — иначе правки наложатся друг на друга.
- Почему происходит
- При заданном
MemoryMax=выделение сверх предела не проходит. Если программа обрабатывает отказ, она сообщает об ошибке вместо смерти.
- Как проверить
-
Сравните предел и потребление.
systemctl show myapp.service -p MemoryMax -p MemoryCurrent -p MemoryPeak
- Как исправить
-
Поднимите предел или уменьшите потребление. Мягкий предел (
MemoryHigh=) замедляет службу вместо отказов.
- Почему происходит
- При исчерпании памяти и отсутствии подкачки выделение падает у всех процессов.
- Как проверить
-
Посмотрите память и записи ядра.
free -h journalctl -k -b --no-pager | grep -i "out of memory" | tail -5
- Как исправить
- Найдите потребителя и ограничьте его. Подкачка помогает пережить пики, но не отменяет разбор.
- Почему происходит
- Предел
vm.max_map_countограничивает число областей на процесс. Службы вроде Elasticsearch упираются в него при значении по умолчанию.
- Как проверить
-
Посмотрите предел и текущее число областей.
sysctl vm.max_map_count PID=$(systemctl show -p MainPID --value myapp.service); wc -l < /proc/$PID/maps
- Как исправить
- Поднимите предел через файл в /etc/sysctl.d.
Пример вывода
Служба упёрлась в собственный предел памяти. Пример показательный: он собран на тестовой машине специально для этой страницы, а не взят из чужого журнала.
myapp[4300]: error: mmap failed: Cannot allocate memory
myapp[4300]: fatal: cannot grow cache: out of memory
systemd[1]: myapp.service: Main process exited, code=exited, status=1/FAILURE
Связанные ошибки
- Failed with result 'oom-kill' Состояние oom-kill: процесс службы убит из-за нехватки памяти. Как понять, упёрлись в предел службы или в память машины.
- status=204/MEMORY в systemd Код 204/MEMORY: systemd не смог выделить память при подготовке запуска службы. Что проверять на машине и в unit-файле.
- Elasticsearch: max virtual memory areas vm.max_map_count is too low Elasticsearch отказывается стартовать из-за заниженного vm.max_map_count. Как поднять значение и закрепить его.
- systemd-oomd остановил службу из-за нехватки памяти Служба остановлена не ядром, а системной службой наблюдения за памятью: критерий другой, и настраивается он иначе.
- Служба замедляется при упоре в MemoryHigh Мягкий предел памяти не убивает, но тормозит. Как заметить давление памяти и отличить его от нехватки.
- Disk quota exceeded для службы Место на разделе есть, а запись отклоняется: исчерпана дисковая квота пользователя или группы.
- Elasticsearch: служба падает из-за размера кучи JVM Размер кучи больше доступной памяти или больше предела службы: падение при старте или под нагрузкой.
- Failed with result 'resources' Состояние resources: systemd не смог выделить ресурсы для запуска службы. Чем отличается от кодов 200-й группы и что проверять.
Где встречается чаще всего
Источники
-
systemd.resource-control(5)
MemoryMax=, MemoryHigh= и поведение при отказе выделения. -
Воспроизведено на тестовой машине, systemd 255 (Ubuntu 24.04)
Воспроизведено на службе с MemoryMax=128M и растущим потреблением.