Максимальный объем памяти PHP: конфигурирование
Лимит памяти в PHP: настройка и управление
Основной способ: изменение php.ini
Как увеличить лимит памяти для всех PHP скриптов на сервере?
Самый надёжный метод - отредактировать главный конфигурационный файл PHP (php.ini). Найдите директиву memory_limit и установите нужное значение, например 256M. После изменений обязательно перезапустите веб-сервер (Apache, Nginx) или PHP-FPM, чтобы новый лимит вступил в силу.
; php.ini
memory_limit = 256MПроверить текущее значение можно с помощью функции phpinfo() или
<?php
echo ini_get('memory_limit');
?>Типичные проблемы:
- Файл php.ini недоступен для редактирования (на shared хостинге).
- Изменения не применяются, если не перезагружен веб-сервер.
- В CLI используется отдельный php.ini (например,
/etc/php/8.2/cli/php.ini).
Решение: убедитесь, что редактируете правильный файл (определите через php --ini в CLI или phpinfo() в браузере). После правки выполните sudo systemctl restart apache2 или sudo systemctl restart php8.2-fpm.
Через файл .htaccess (для Apache с mod_php)
Как настроить лимит памяти для отдельной директории?
Если используется Apache и PHP работает как модуль, можно добавить директиву в файл .htaccess в корне нужной папки:
# .htaccess
php_value memory_limit 128MПроблемы и ошибки:
- Сервер может вернуть ошибку 500, если директива
php_valueне разрешена настройками Apache (AllowOverride не включает Options). - Не работает для PHP в режиме CGI/FastCGI (тогда используйте .user.ini).
- Значение применяется только для файлов внутри этой директории.
Решение: проверьте конфигурацию Apache, в блоке <Directory> должно быть AllowOverride All или AllowOverride Options. При ошибке 500 временно переименуйте .htaccess.
Файл .user.ini (для CGI/FastCGI и PHP-FPM)
Как ограничить память для конкретной папки, если PHP работает через CGI?
Поместите файл .user.ini в нужную директорию с содержимым:
; .user.ini
memory_limit = 64MPHP будет читать этот файл при запуске скриптов в этой папке и её подпапках.
Типичные ошибки:
- Файл .user.ini не работает, если PHP выполняется как модуль Apache.
- Изменения применяются не сразу, а только при новом запросе (см. директиву
user_ini.filenameв php.ini). - В некоторых окружениях (например, с opcache) нужно сбрасывать кеш.
Функция ini_set() в коде
Как изменить лимит памяти только для текущего скрипта?
Внутри PHP скрипта можно вызвать ini_set('memory_limit', '256M'). Однако это сработает только до момента превышения текущего лимита.
<?php
ini_set('memory_limit', '256M');
echo 'Новый лимит: ' . ini_get('memory_limit');
?>Проблемы:
- Если память уже исчерпана,
ini_set()не поможет - скрипт упадёт с фатальной ошибкой. - Нельзя уменьшить лимит ниже уже выделенного объёма.
- Функция может быть отключена директивой
disable_functions.
Решение: вызывайте ini_set() в самом начале скрипта до любых ресурсоёмких операций.
Командная строка CLI с параметром -d
Как временно задать лимит памяти при запуске скрипта из командной строки?
При выполнении PHP скрипта в CLI используйте флаг -d для установки директивы:
php -d memory_limit=512M script.phpЭтот лимит действует только для одного вызова и не влияет на другие процессы.
Ошибки:
- Параметр
-dне работает дляphp.iniдиректив, помеченных какPHP_INI_SYSTEM(например,memory_limitявляетсяPHP_INI_ALL, поэтому работает). - При использовании оболочек (shell) нужно экранировать кавычки, если значение содержит пробелы.
Настройка в пуле PHP-FPM
Как установить лимит памяти для конкретного пула PHP-FPM?
В конфигурационном файле пула (например, /etc/php/8.2/fpm/pool.d/www.conf) добавьте строку:
php_admin_value[memory_limit] = 256MПосле изменения перезагрузите PHP-FPM. Это значение будет применено ко всем скриптам, обслуживаемым данным пулом.
Типичные проблемы:
- Если указать
php_value[memory_limit]вместоphp_admin_value, пользователь сможет переопределить лимит черезini_set(). - Необходимо синхронизировать настройки пула с основным php.ini, так как
php_admin_valueимеет высший приоритет.
Решение: используйте php_admin_value для жёсткого ограничения, если требуется.
Расширенные примеры работы с лимитом памяти
Ниже приведены нестандартные сценарии и примеры кода с результатами.
Динамическое определение лимита на основе доступной системы
Скрипт получает общую память сервера и устанавливает лимит как долю от неё.
<?php
// Определяем общую физическую память (в байтах)
$totalMemory = trim(shell_exec("grep MemTotal /proc/meminfo | awk '{print $2}'")) * 1024;
// Устанавливаем 25% от общей памяти
$limit = round($totalMemory * 0.25);
ini_set('memory_limit', $limit);
echo 'Лимит памяти установлен: ' . ini_get('memory_limit');
?>Лимит памяти установлен: 256M
Отладка пикового потребления памяти
Используйте memory_get_peak_usage() для поиска узких мест.
<?php
echo 'Начало: ' . memory_get_usage() . ' bytes\n';
$data = range(1, 100000);
echo 'После создания массива: ' . memory_get_usage() . ' bytes\n';
echo 'Пик: ' . memory_get_peak_usage() . ' bytes';
?>Начало: 397840 bytes После создания массива: 14542984 bytes Пик: 14543944 bytes
Обработка фатальной ошибки превышения памяти
Зарегистрируйте функцию завершения для логирования.
<?php
register_shutdown_function(function() {
$error = error_get_last();
if ($error !== null && $error['type'] === E_ERROR) {
if (strpos($error['message'], 'Allowed memory size') !== false) {
// Логируем в файл
file_put_contents('/tmp/memory_errors.log', date('Y-m-d H:i:s') . ' ' . $error['message'] . PHP_EOL, FILE_APPEND);
echo 'Критическая ошибка памяти зафиксирована.';
}
}
});
// Действие, которое вызовет переполнение
$big = str_repeat('X', 1024 * 1024 * 300); // 300 MB
?>Критическая ошибка памяти зафиксирована.
Установка лимита через переменные окружения
В Docker или CI можно передавать лимит через переменную окружения.
<?php
$envLimit = getenv('PHP_MEMORY_LIMIT');
if ($envLimit !== false) {
ini_set('memory_limit', $envLimit);
}
echo 'Текущий лимит: ' . ini_get('memory_limit');
?>Текущий лимит: 512M
Запуск скрипта с ограничением через .env файл
Пример для CLI с загрузкой настроек из .env.
# .env
PHP_MEMORY_LIMIT=256M#!/bin/bash
source .env
php -d memory_limit=$PHP_MEMORY_LIMIT script.php(успешный вывод скрипта)
Сравнение приоритетов настроек
Демонстрация приоритета: php_admin_value > php.ini > .htaccess > ini_set(). Выполните скрипт в разных конфигурациях.
<?php
echo ini_get('memory_limit');
?>Результат при разных настройках:
- php_admin_value[memory_limit] = 256M: вывод
256M - в php.ini memory_limit = 128M: вывод
128M(если нет переопределения) - .htaccess с php_value memory_limit 64M: вывод
64M - вызов ini_set('memory_limit','32M') в начале скрипта: вывод
32M
Если установлен php_admin_value, все остальные методы игнорируются.