Сообщения вида cannot allocate memory linux, fork cannot allocate memory или ssh cannot allocate memory появляются в момент, когда системе уже тяжело обслуживать новые процессы или выделять память. И почти всегда это не история уровня «просто закончилась оперативка».
На Debian и Ubuntu ошибка может быть связана с исчерпанием RAM, отсутствием swap, жёсткой политикой vm.overcommit_memory, лимитами на количество процессов, cgroup-ограничениями контейнера или сервиса, а также с обычной утечкой памяти в приложении.
Самый неприятный сценарий — когда перестаёт открываться новая SSH-сессия. Порт ещё отвечает, аутентификация может даже пройти, но дальше сервер уже не может породить shell или дочерний процесс. В этот момент важно не паниковать и не закрывать последнюю живую консоль.
Ниже разберём, как быстро отличить реальный дефицит памяти от лимитов процессов, какие команды запускать в первую очередь, как аккуратно вернуть сервер в рабочее состояние и что поменять, чтобы инцидент не повторился.
Что на самом деле означает Cannot allocate memory
Ошибка возникает, когда процесс просит ядро выделить память или создать дочерний процесс, а ядро не может гарантировать выполнение запроса. Очень часто это проявляется на вызове fork(), потому что даже для короткоживущего дочернего процесса нужны служебные структуры, таблицы страниц и ресурсы учёта.
Из-за этого симптоматика бывает обманчивой. В системе может оставаться часть памяти в page cache, но форк уже не проходит. Или RAM визуально ещё не заполнена на 100%, однако система уткнулась в CommitLimit, лимит контейнера или ограничение на количество процессов.
Ключевая мысль простая:
fork cannot allocate memoryне означает автоматически «физическая память полностью кончилась». Это более широкий сигнал о том, что ядро не может безопасно обслужить запрос на новый процесс или выделение памяти.
Типовые причины на Debian и Ubuntu
Закончилась RAM и нет swap
Это классический сценарий. PHP-FPM, база данных, Java, Node.js, очереди, Docker-контейнеры или просто слишком много воркеров постепенно занимают всю память. Если swap отсутствует или слишком мал, запас прочности у системы быстро заканчивается.
Есть RAM, но исчерпан commit limit
Linux учитывает не только занятую физическую память, но и объём виртуальной памяти, который процессы уже зарезервировали. На поведение влияет vm.overcommit_memory. Поэтому ошибка может появиться раньше, чем вы увидите «полный ноль» в обычном выводе free.
Слишком много процессов или потоков
Иногда первопричина — не память как таковая, а лавина процессов: runaway-воркеры, рекурсивный cron, ошибка в supervisor, неудачная конфигурация пула, форк-бомба. Каждый процесс потребляет память и системные ресурсы, поэтому лимит быстро упирается в потолок.
Лимиты systemd, контейнера или cgroup
На хосте память ещё может оставаться, но конкретный сервис уже умирает внутри собственных ограничений. Особенно часто это видно в Docker, Kubernetes и systemd unit с параметрами MemoryMax и TasksMax.
Утечки памяти
Если сервис медленно растёт часами или днями, авария обычно происходит не на пике нагрузки, а в случайный момент. Такие истории часто встречаются у веб-приложений, фоновых обработчиков, кэшей и долгоживущих воркеров.
Если проект уже перерос базовый профиль нагрузки и вы регулярно упираетесь в память, стоит заранее пересмотреть размер инстанса или переехать на более подходящий VDS, где проще контролировать swap, лимиты и профиль сервисов.

Как проявляется проблема с SSH
Ошибка ssh cannot allocate memory означает, что серверу не хватает ресурсов даже на создание shell после логина. Сам sshd ещё может слушать порт и принимать соединение, но дальнейшая обработка уже ломается.
Часто это выглядит так:
ssh: fork: Cannot allocate memory
Или так:
-bash: fork: retry: Resource temporarily unavailable
-bash: fork: Cannot allocate memory
Сообщение Resource temporarily unavailable важно не меньше, чем Cannot allocate memory. Оно часто указывает на лимиты процессов, а не только на нехватку RAM. Поэтому диагностика должна быть шире, чем одна команда free -h.
Первичная диагностика: что смотреть сразу
Если у вас ещё осталась хотя бы одна рабочая сессия, не закрывайте её. Это аварийная точка входа. Задача на первом этапе — быстро понять, проблема в памяти, в процессных лимитах или в ограничении конкретного сервиса.
Проверить память и swap
free -h
swapon --show
cat /proc/meminfo | egrep 'MemAvailable|SwapTotal|SwapFree|Committed_AS|CommitLimit'
Смотрите прежде всего на MemAvailable, наличие swap и соотношение Committed_AS к CommitLimit. Если swap отсутствует, а доступная память почти нулевая, причина, скорее всего, в реальном дефиците памяти.
Проверить OOM killer
dmesg -T | egrep -i 'killed process|out of memory|oom'
journalctl -k -b | egrep -i 'killed process|out of memory|oom'
Если ядро уже кого-то убивало, в логах будут PID, имя процесса и объём памяти. Это обычно самый короткий путь к виновнику.
Найти самые прожорливые процессы
ps aux --sort=-%mem | head -20
ps -eo pid,ppid,user,cmd,%mem,%cpu,rss,vsz --sort=-rss | head -20
Ориентируйтесь на RSS и на общую сумму по группе процессов. Один процесс на 300 МБ может быть менее опасен, чем 30 воркеров по 120 МБ.
Проверить лимиты процессов
ulimit -a
cat /proc/sys/kernel/pid_max
cat /proc/sys/kernel/threads-max
ps -eLf | wc -l
Если число потоков и процессов близко к системным лимитам, форк может ломаться даже без абсолютного нуля по памяти.
Проверить ограничения systemd
systemctl show ssh -p MemoryCurrent -p MemoryMax -p TasksCurrent -p TasksMax
systemctl show php8.2-fpm -p MemoryCurrent -p MemoryMax -p TasksCurrent -p TasksMax
systemctl status
Подставьте свои юниты. Если у сервиса занижен MemoryMax или TasksMax, проблема может быть локальной, а не системной.
Как срочно вернуть сервер в чувство
На аварийном этапе цель простая: восстановить управляемость и не ухудшить ситуацию. Не запускайте тяжёлые диагностические утилиты, если сервер уже задыхается.
Если есть открытая SSH-сессия
Найдите самый тяжёлый процесс и попытайтесь остановить его мягко. Если не помогает — завершайте жёстко.
ps -eo pid,cmd,%mem,rss --sort=-rss | head -15
kill -TERM PID
sleep 3
kill -KILL PID
Обычно безопаснее начать с runaway-воркеров, дублирующихся контейнеров, зависших импортёров, очередей или тестовых процессов, а не с базы данных.
Если виноват конкретный сервис
systemctl stop php8.2-fpm
systemctl stop apache2
systemctl stop docker
Останавливайте только то, последствия чего вы понимаете. На production лучше отключить один проблемный юнит, чем вслепую уронить весь стек.
Если swap отсутствует
В аварийной ситуации swap-файл часто помогает вернуть SSH и дать системе немного воздуха. Это не панацея, но как временная страховка работает хорошо.
fallocate -l 1G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
free -h
Если fallocate не подходит для вашей файловой системы, используйте альтернативу:
dd if=/dev/zero of=/swapfile bs=1M count=1024 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
Если после временной стабилизации вы планируете оставить swap насовсем, добавьте запись в /etc/fstab.
На проектах, где ресурсов уже не хватает даже после базовой оптимизации, полезно заранее планировать миграцию или расширение. Если вы как раз выбираете схему переноса, посмотрите материал про переезд с виртуального хостинга на VDS.
Роль vm.overcommit_memory
Параметр vm.overcommit_memory управляет тем, насколько оптимистично ядро относится к резервированию памяти приложениями.
0— эвристический режим по умолчанию;1— почти всегда разрешать overcommit;2— строгий режим, без выхода за commit limit.
Для большинства обычных серверов подходит 0. Если кто-то включил 2, некоторые приложения могут получать fork cannot allocate memory заметно раньше ожидаемого.
sysctl vm.overcommit_memory
sysctl vm.overcommit_ratio
Для диагностики можно временно вернуть стандартный режим:
sysctl -w vm.overcommit_memory=0
Или протестировать более либеральное поведение:
sysctl -w vm.overcommit_memory=1
vm.overcommit_memoryне добавляет системе реальную память. Он лишь меняет политику допуска к резервированию. Если источник проблемы — runaway-процесс или неверный sizing, менять нужно именно их.
Постоянную настройку лучше выносить в отдельный файл в /etc/sysctl.d/ и применять только после понимания нагрузки и поведения приложений.

Когда виноват не RAM, а лимит на процессы
Если система не может делать fork, проверьте не только память, но и число процессов на пользователя, сервис и систему. Особенно это важно на серверах с CI-задачами, контейнерами, большим числом воркеров и плотным cron.
ulimit -u
cat /etc/security/limits.conf
grep -R nproc /etc/security/limits.d
Для systemd-сервисов полезно посмотреть:
systemctl show your-service -p TasksMax
systemctl cat your-service
Если сервис уткнулся в TasksMax, симптомы очень похожи на нехватку памяти: новые процессы не стартуют, SSH ведёт себя нестабильно, часть команд не выполняется. Но простое увеличение лимита без поиска причины часто только откладывает повторение проблемы.
Частые источники memory exhaustion на практике
PHP-FPM
Очень частый источник аварий на веб-серверах. Неверно выбранный pm.max_children быстро съедает всю память. Оценивать пул нужно по реальному потреблению воркеров, а не по усреднённым советам.
MySQL и PostgreSQL
На маленьких серверах опасны завышенные буферы и параметры, которые умножаются на число соединений. Итог — память уходит в базу, а системе уже не хватает ресурсов на остальные процессы.
Docker-контейнеры без лимитов
Один runaway-процесс внутри контейнера легко уносит весь хост, если нет memory limits. Особенно неприятно, когда от этого перестаёт работать SSH.
Java и другие тяжёлые сервисы
Heap, кэши и фоновые потоки должны вписываться в общий memory budget сервера. Иначе приложение живёт на грани OOM даже при средней нагрузке.
Как предотвратить повторение инцидента
Добавьте swap
На небольшом сервере swap — это страховка, а не роскошь. Он не заменяет RAM, но помогает пережить краткие пики и сохранить доступ для аварийного входа.
Настройте мониторинг
Минимальный набор метрик: RAM, swap, число процессов, RSS по ключевым сервисам, события OOM killer, а также pressure по памяти. Без исторических графиков утечки памяти почти всегда замечают слишком поздно.
Ограничьте прожорливые сервисы
Используйте MemoryMax и TasksMax в systemd, memory limits в контейнерах, корректный размер пула в PHP-FPM, разумные настройки heap в Java. Задача — добиться контролируемой деградации, а не падения всего хоста.
Проверьте baseline sysctl
Если кто-то менял vm.overcommit_memory или vm.swappiness без понятной причины, лучше вернуться к адекватной базовой конфигурации и заново протестировать нагрузку.
Планируйте ресурсы заранее
Если проект стабильно растёт, полезно не только тушить инциденты, но и пересматривать capacity plan. Для небольших сайтов и типовых PHP-проектов часть проблем решается на правильно подобранном виртуальном хостинге, а для более требовательных сервисов — на выделенном профиле ресурсов. Если оптимизируете PHP на shared-среде, может пригодиться статья про настройку PHP, OPcache и Brotli на виртуальном хостинге.
Пошаговый чек-лист
- Не закрывайте текущую рабочую SSH-сессию.
- Проверьте
free -h,swapon --showи показатели из/proc/meminfo. - Посмотрите
dmesgиjournalctl -k -bна признаки OOM. - Найдите процессы с максимальным RSS.
- Проверьте
ulimit, число потоков иTasksMax. - Остановите runaway-процесс или проблемный сервис.
- Если swap нет, добавьте временный swap-файл.
- После стабилизации зафиксируйте корневую причину и измените конфигурацию, а не только перезагрузите сервер.
Вывод
Ошибки fork cannot allocate memory, ssh cannot allocate memory и похожие сообщения почти всегда указывают на серьёзный перекос в ресурсах или лимитах. На Debian и Ubuntu корень обычно находится в одном из четырёх мест: реально закончилась память, отсутствует swap, неверно настроен overcommit или система уткнулась в лимиты процессов и cgroup.
Правильная последовательность действий такая: сначала сохранить доступ и вернуть управляемость, затем быстро найти виновника по логам и фактическому потреблению памяти, а после — исправить sizing, лимиты и мониторинг. Перезагрузка помогает ненадолго. Понимание причины помогает не ловить ту же аварию снова.


