Как увеличить memory_limit в PHP на Ubuntu

Лимит памяти PHP, memory_limit, ограничивает, сколько памяти может занять один скрипт, по умолчанию 128 МБ. Рядом живут лимиты, которые обычно меняют заодно: размер загружаемого файла, всей формы и время работы скрипта. На Ubuntu сложнее всего найти нужный файл: командная строка, PHP-FPM и Apache читают каждый свой php.ini. Инструкция для PHP 8.3 на Ubuntu 24.04. В 22.04 стоит PHP 8.1, так что в путях и именах служб пишите 8.1. Свою версию покажет команда: ls /etc/php/

Какой php.ini читает ваш PHP

В Ubuntu у каждого способа запуска PHP свои настройки: /etc/php/8.3/cli/php.ini для терминала, /etc/php/8.3/fpm/php.ini для PHP-FPM за Nginx и /etc/php/8.3/apache2/php.ini для mod_php в Apache. Рядом с каждым лежит папка conf.d/, её файлы читаются после php.ini. Первая из этих команд показывает только файлы терминала, о сайте она ничего не скажет:

php --ini php -r 'echo ini_get("memory_limit"), PHP_EOL;' sudo php-fpm8.3 -i | grep -E '^(memory_limit|upload_max_filesize|post_max_size|max_execution_time)'

В терминале Ubuntu обычно покажет -1: в его php.ini лимита памяти нет. Последняя команда покажет, что PHP-FPM берёт из своих php.ini и conf.d. Значения из пула и .user.ini она не видит, поэтому последнее слово за phpinfo() на самом сайте: смотрите Loaded Configuration File, Additional .ini files parsed и Local Value у memory_limit. Такую страницу удалите сразу после проверки.

Как поднять memory_limit, upload_max_filesize и post_max_size

Свои значения положите в отдельный файл в conf.d: он читается после php.ini и побеждает, а обновления пакетов его не трогают. Правило из документации PHP: post_max_size должен быть больше upload_max_filesize, а memory_limit, как правило, больше post_max_size. Для PHP-FPM:

sudo nano /etc/php/8.3/fpm/conf.d/99-limits.ini
/etc/php/8.3/fpm/conf.d/99-limits.ini
memory_limit = 256M upload_max_filesize = 50M post_max_size = 60M max_execution_time = 60
sudo php-fpm8.3 -t sudo systemctl restart php8.3-fpm

С Apache и mod_php положите такой же файл в /etc/php/8.3/apache2/conf.d/ и выполните:

sudo systemctl restart apache2

Для скриптов в терминале и cron — в /etc/php/8.3/cli/conf.d/, перезапуск там не нужен. Поднимайте memory_limit постепенно, до 256M или 512M, а не до -1: лимит останавливает один сломанный запрос раньше, чем тот съест память всего сервера.

Загрузка файлов: три лимита, а не два

Загружаемый файл проходит три проверки, и действует самая строгая:

  • upload_max_filesize (по умолчанию 2 МБ) — размер одного файла. Файл больше приходит с кодом ошибки UPLOAD_ERR_INI_SIZE в $_FILES, остальные поля формы при этом на месте.
  • post_max_size (по умолчанию 8 МБ) — весь запрос со всеми файлами и полями. Если запрос больше, $_POST и $_FILES пустые, а в журнале PHP Warning: POST Content-Length of … bytes exceeds the limit of 8388608 bytes.
  • client_max_body_size в Nginx (по умолчанию 1 МБ) — Nginx отвечает 413 Request Entity Too Large раньше, чем PHP что-то увидит. Поднимите его в блоке server сайта, как в статье как настроить Nginx reverse proxy.

Лимиты для одного сайта: пул FPM, .user.ini и ini_set

В пуле PHP-FPM можно задать значения только для одного сайта. php_admin_value код сайта поменять не сможет, php_value — сможет. Добавьте строки в файл пула этого сайта, например www.conf, и перезапустите PHP-FPM:

/etc/php/8.3/fpm/pool.d/www.conf
php_admin_value[memory_limit] = 512M php_admin_value[upload_max_filesize] = 100M php_admin_value[post_max_size] = 110M

Если доступа к настройкам сервера нет, положите файл .user.ini в корневую папку сайта. PHP-FPM читает его для скриптов в этой папке и ниже, и работают в нём только настройки, которые разрешено менять по папкам: memory_limit, upload_max_filesize, post_max_size и max_execution_time — можно. PHP перечитывает его раз в 5 минут (user_ini.cache_ttl), так что подождите или перезапустите PHP-FPM. С mod_php в Apache .user.ini не читается — там то же делает строка php_value memory_limit 256M в .htaccess.

/var/www/example.com/.user.ini
memory_limit = 256M upload_max_filesize = 50M post_max_size = 60M

В коде ini_set('memory_limit', '512M') поднимает лимит для одного скрипта, например для выгрузки, а set_time_limit(120) — то же для времени. Для upload_max_filesize и post_max_size они не работают: когда код запустился, запрос уже принят. И против php_admin_value они тоже бессильны.

max_execution_time и таймауты

max_execution_time для сайта по умолчанию 30 секунд, в терминале — без ограничения. В Linux он считает только работу самого скрипта, а не ожидание базы, файлов или другого сервера, так что скрипт, который ждёт медленный API, может идти гораздо дольше. Когда время выходит, скрипт останавливается с Fatal error: Maximum execution time of 30 seconds exceeded. Вокруг есть ещё два лимита:

  • fastcgi_read_timeout в Nginx, по умолчанию 60 секунд — после него Nginx отдаёт посетителю 504 Gateway Time-out, даже если PHP ещё работает.
  • request_terminate_timeout в пуле FPM, по умолчанию выключен — убивает процесс PHP по истечении времени, чего бы тот ни ждал.

Веб-запросы держите короткими. Долгие задачи вроде импорта и отчётов запускайте из терминала, cron или очереди, там max_execution_time не действует.

Как исправить «Allowed memory size of 134217728 bytes exhausted»

Полностью ошибка выглядит так: PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes). Первое число — текущий лимит в байтах: 134217728 — это 128 МБ, 268435456 — 256 МБ. Если после правки число не изменилось, скрипт работает не в том SAPI или пуле, чей файл вы правили: проверьте через phpinfo() на сайте, а для терминала и cron — командами из первого раздела.

  • Ошибка на тяжёлой странице, при импорте или обработке картинки — поднимите memory_limit для этого сайта или для этого скрипта через ini_set.
  • Ошибка остаётся при любом лимите — код грузит слишком много сразу, например всю таблицу в массив, или зациклился. Читайте данные частями. Файл и строка в сообщении показывают, где кончилась память.
  • Ошибку выдаёт Composer. Так лимит снимается только на один запуск: COMPOSER_MEMORY_LIMIT=-1 composer update

Если вы работаете и на Mac

MacWashing, раздел «Сборка мусора»: найдены мусор Xcode, пользовательский кэш, установщики и журналы, к очистке 22,83 ГБ

Сборка мусора в MacWashing находит кэш всех знакомых ей программ, в том числе спрятанный внутри их данных, а ещё журналы, мусор Xcode и остатки удалённых программ. Она показывает, сколько места занимает каждая находка, и очищает всё за один раз. Всё спорное остаётся без галочки, пока вы не решите.

Бесплатная пробная версия · macOS 14 и новее

Вопросы и ответы

Какой memory_limit в PHP по умолчанию?

128 МБ для сайта в PHP-FPM и Apache. В терминале на Ubuntu лимита нет: в /etc/php/8.3/cli/php.ini стоит memory_limit = -1.

Можно ли поставить memory_limit = -1 на веб-сервере?

Не стоит. Тогда один запрос с ошибкой может занять всю память и замедлить или уронить сервер. Дайте сайту настоящий лимит, а снимайте его только для скриптов в терминале, которым доверяете.

Я поменял php.ini, а ничего не изменилось. Почему?

Обычно это не тот файл (cli/php.ini терминала вместо fpm/php.ini), PHP-FPM не перезапущен или своё значение задаёт пул либо .user.ini. phpinfo() на сайте покажет, какой файл и какое значение действуют.