Управление временем работы скриптов PHP через max_execution_time
Основные способы настройки max_execution_time
Наиболее эффективное решение
Для изменения максимального времени выполнения скрипта в PHP рекомендуется использовать функцию set_time_limit() или директиву ini_set('max_execution_time', ...). Эти методы позволяют задать ограничение непосредственно в коде, не затрагивая глобальные настройки сервера. При вызове set_time_limit(30) таймер сбрасывается и начинает отсчёт заново. Это удобно, когда нужно продлить время выполнения в середине работы скрипта.
<?php
// Установка времени выполнения 60 секунд
set_time_limit(60);
// Альтернативный способ с ini_set
ini_set('max_execution_time', 60);
// Выполнение длительной операции
sleep(2);
echo "Скрипт выполнен за 2 секунды.";
?>Php open basedir (директива open_basedir в php)
Типичные проблемы
При использовании ini_set изменение может не сработать, если скрипт работает в режиме безопасного режима (устарело) или если значение уже превышено. В некоторых SAPI (например, PHP-FPM) директива может быть переопределена конфигурацией пула. Также следует помнить, что set_time_limit() не продлевает время выполнения, если скрипт уже превысил лимит.
Как изменить max_execution_time через php.ini?
Изменение глобального значения для всех скриптов на сервере производится в файле php.ini. Настройка применяется после перезагрузки веб-сервера или PHP-FPM.
; Установить 120 секунд
max_execution_time = 120Php max execution (максимальное время выполнения скрипта в php (max_execution_time))
После изменения перезагрузите сервер: sudo systemctl restart apache2 sudo systemctl restart php-fpm
Php max vars (максимальное количество переменных в php (max_input_vars))
Возможные ошибки
Если после изменения php.ini значения не обновляются, проверьте, какой файл php.ini загружен (вызов phpinfo()). Возможно, используется конфигурация пула (для FPM) или .htaccess переопределяет настройку.
Как установить лимит через .htaccess?
Для серверов Apache с mod_php или CGI/FastCGI можно задать директиву в .htaccess.
# Установить 300 секунд
php_value max_execution_time 300
Проблемы с .htaccess
Директива php_value разрешена не во всех контекстах (требуется AllowOverride Options). Для PHP-FPM через Apache директивы .htaccess игнорируются, вместо них нужно настраивать пул.
Как отключить ограничение времени (установить бесконечное выполнение)?
Для скриптов, которые должны работать без временного лимита, можно установить значение 0.
set_time_limit(0);
// или
ini_set('max_execution_time', 0);
Риски безопасности
Отключение лимита может привести к зависанию скрипта и перегрузке сервера. Рекомендуется использовать только для коротких операций с контролем через другие механизмы (например, тайм-аут базы данных).
Как настроить max_execution_time в PHP-FPM pool?
В конфигурации пула (например, /etc/php/8.2/fpm/pool.d/www.conf) можно задать параметры.
; Значение 600 секунд
pm.max_execution_time = 600
; или
request_terminate_timeout = 600
Различие параметров
Параметр pm.max_execution_time влияет на время исполнения скрипта в пуле, а request_terminate_timeout жестко обрывает процесс, если скрипт превысил лимит. Второй вариант более надёжен.
Как проверить текущее значение max_execution_time?
Можно использовать ini_get() или проанализировать вывод phpinfo().
echo 'Текущее ограничение: ' . ini_get('max_execution_time') . ' секунд';
Текущее ограничение: 30 секунд
Как обработать превышение времени выполнения?
При выходе за лимит PHP генерирует фатальную ошибку. Её можно перехватить с помощью register_shutdown_function или установить пользовательский обработчик ошибок.
register_shutdown_function(function() {
$error = error_get_last();
if ($error && $error['type'] === E_ERROR) {
// Если ошибка связана с max_execution_time
if (strpos($error['message'], 'Maximum execution time') !== false) {
echo "Скрипт превысил лимит времени.\n";
// Логирование, запись в БД и т.д.
}
}
});
set_time_limit(1); // Заведомо мало
while (true) {}
?>
Скрипт превысил лимит времени.
Расширенные примеры работы с max_execution_time
Пример 1. Продление таймера в цикле
При выполнении длительных итеративных задач полезно периодически сбрасывать таймер, чтобы избежать прерывания.
<?php
// Обработка 1000 записей с limit 5 секунд на итерацию
set_time_limit(0); // отключаем общий лимит для безопасности? Нет, лучше продлевать
for ($i = 0; $i < 1000; $i++) {
// Каждые 10 итераций сбрасываем таймер на 30 секунд
if ($i % 10 === 0) {
set_time_limit(30);
}
// Выполнение тяжелой операции
usleep(50000); // 0.05 сек
}
echo "Готово";
?>
Вывод: "Готово" (скрипт завершился без превышения лимита)
Пример 2. Использование try-catch для обработки ошибки превышения (эмуляция)
Фатальная ошибка не может быть перехвачена try-catch, но можно использовать register_shutdown_function вместе с error_get_last.
<?php
// Имитация длительной работы
function heavyTask() {
while (true) {
// Делаем что-то
}
}
register_shutdown_function(function() {
$lastError = error_get_last();
if ($lastError !== null && $lastError['type'] === E_ERROR) {
echo ""Поймана фатальная ошибка: " . $lastError['message'] . "\n"";
exit;
}
});
set_time_limit(2);
heavyTask();
?>
Поймана фатальная ошибка: Maximum execution time of 2 seconds exceeded in ...
Пример 3. Настройка через .htaccess для конкретного каталога
В каталоге /admin/ скрипты могут требовать больше времени.
# .htaccess в папке /admin/
php_value max_execution_time 600
php_value memory_limit 256M
Пример 4. Сравнение поведения в CLI и веб-среде
В командной строке max_execution_time по умолчанию равно 0 (без ограничения). Проверим:
$ php -r 'echo ini_get("max_execution_time");'
0
Пример 5. Использование PHP-FPM request_terminate_timeout для жесткого контроля
# /etc/php/8.2/fpm/pool.d/www.conf
request_terminate_timeout = 60s
; Если скрипт не завершится за 60 секунд, процесс будет уничтожен SIGTERM
Пример 6. Пользовательская функция для безопасного выполнения с лимитом
<?php
function executeWithTimeLimit(callable $callback, int $timeLimitSeconds) {
$shutdown = function() use ($timeLimitSeconds) {
$error = error_get_last();
if ($error !== null && $error['type'] === E_ERROR && stripos($error['message'], 'Maximum execution time') !== false) {
// Логируем и возвращаем false
echo "Функция превысила лимит в {$timeLimitSeconds} секунд.";
}
};
register_shutdown_function($shutdown);
set_time_limit($timeLimitSeconds);
return $callback();
}
// Использование
$result = executeWithTimeLimit(function() {
// Долгий код
sleep(100);
return true;
}, 10);
?>
Функция превысила лимит в 10 секунд.