Увеличение периода выполнения PHP кода для предотвращения ошибок timeout

Раздел: PHP -> Управление ошибками PHP

Способы увеличения времени выполнения PHP скриптов

Как программно изменить максимальное время выполнения скрипта?

Наиболее гибкий способ - использовать функцию set_time_limit() прямо в коде. Она позволяет установить лимит времени для текущего скрипта, при этом отсчёт начинается с момента вызова. Если передать 0, ограничение снимается.

set_time_limit(120); // 120 секунд
// или без лимита:
// set_time_limit(0);

Time out php (увеличение времени выполнения скрипта php)

Функция set_time_limit() перезаписывает директиву max_execution_time из php.ini. Если скрипт уже работал некоторое время, новый отсчёт начнётся с текущего момента. Это удобно для длительных операций, например, обработки больших CSV-файлов или генерации отчётов.

Типичные проблемы:

  • На некоторых хостингах вызов set_time_limit() может быть запрещён (директива disable_functions). В этом случае потребуется другой подход.
  • Если скрипт превышает время, PHP выдаёт фатальную ошибку Fatal error: Maximum execution time exceeded. Обработать её через try-catch нельзя, но можно зарегистрировать функцию через register_shutdown_function() для выполнения действий перед завершением.
  • При использовании set_time_limit(0) скрипт может выполняться бесконечно, что нагружает сервер. Рекомендуется всегда задавать разумный лимит.

Как установить глобальный лимит времени выполнения для всех скриптов?

Измените директиву max_execution_time в файле php.ini. Найдите строку max_execution_time = 30 и замените на нужное значение (в секундах). Для unbounded укажите 0.

max_execution_time = 120

После изменения перезапустите веб-сервер (Apache, Nginx) или PHP-FPM. Изменение повлияет на все скрипты, работающие в этом окружении.

Проблемы:

  • Если у вас нет доступа к php.ini (например, на общем хостинге), этот вариант недоступен.
  • Глобальная настройка может снизить безопасность: если какой-то скрипт зависнет, он будет потреблять ресурсы дольше.

Как временно изменить директиву из кода без прав на php.ini?

Функция ini_set() позволяет переопределить значение директивы max_execution_time на время выполнения текущего скрипта. Однако не все директивы можно менять в рантайме (это зависит от режима - PHP_INI_ALL или PHP_INI_PERDIR). Директива max_execution_time относится к PHP_INI_ALL, поэтому её можно использовать в скрипте.

ini_set('max_execution_time', 300); // 5 минут

Эффект аналогичен set_time_limit(), но при этом отсчёт начинается с момента начала выполнения скрипта, а не с момента вызова. При использовании ini_set() после некоторого времени скрипта, лимит может быть уже частично исчерпан. Поэтому предпочтительнее set_time_limit().

Ошибки:

  • Если директива не разрешена для изменения (например, если хостинг ограничил ini_set для max_execution_time), вызов не повлияет на лимит.
  • Использование ini_set() для установки 0 также снимет ограничение.

Как настроить таймаут через конфигурацию веб-сервера для конкретной директории?

Если используется Apache, можно добавить директиву php_value max_execution_time в файл .htaccess в нужной директории. Для этого должен быть включён модуль mod_php.

# .htaccess
php_value max_execution_time 120

Аналогично можно использовать php_admin_value, если у вас есть доступ к основному конфигу Apache. На Nginx такой подход не работает - там используется FastCGI, и директивы передаются через настройки PHP-FPM.

Проблемы:

  • Директива php_value работает только в Apache с mod_php. В режиме FastCGI/FPM она игнорируется.
  • Некоторые хостинги запрещают использование php_value в .htaccess из соображений безопасности.

Как увеличить время ожидания ответа от PHP при использовании сервера Apache или Nginx?

Помимо внутреннего таймаута PHP существуют таймауты на уровне веб-сервера. Для Apache директива Timeout задаёт максимальное время ожидания ответа от PHP-процесса (в секундах).

# Apache в httpd.conf или virtual host
Timeout 180

Для Nginx используется директива proxy_read_timeout (если PHP работает через FastCGI, то fastcgi_read_timeout).

# Nginx в server или location block
location ~ \.php$ {
    fastcgi_read_timeout 180;
    ...
}

Эти настройки должны быть не меньше, чем лимит PHP, иначе скрипт будет прерван сервером раньше.

Возможные ошибки:

  • Несоответствие таймаутов: если PHP настроен на 300 секунд, а сервер на 120, скрипт будет прерван сервером.
  • В некоторых случаях (например, при использовании балансировщиков) могут быть дополнительные таймауты.

Расширенные примеры настройки времени выполнения PHP

Пример 1. Использование set_time_limit() с учётом уже прошедшего времени

Функция set_time_limit() сбрасывает счётчик на ноль. Если скрипт уже выполнялся 10 секунд, а вы вызываете set_time_limit(30), то общий лимит станет 10 + 30 = 40 секунд. Это позволяет продлевать время для длительных операций.

Пример
echo "Начало выполнения: " . date('H:i:s') . "\n";
// Эмуляция 5-секундной работы
sleep(5);
echo "Прошло 5 секунд, вызываем set_time_limit(10)\n";
set_time_limit(10);
sleep(8); // всего прошло 13 секунд, лимит 10 с момента вызова, но осталось 2 секунды
echo "Скрипт завершился через 13 секунд, лимит не превышен";
Начало выполнения: 10:00:00
Прошло 5 секунд, вызываем set_time_limit(10)
Скрипт завершился через 13 секунд, лимит не превышен

Если бы sleep(8) заменить на sleep(12), скрипт был бы прерван.

Пример 2. Снятие ограничения времени через set_time_limit(0) и контроль ресурсов

Установка нуля означает бесконечное выполнение. Это может быть опасно, поэтому используйте вместе с проверкой времени вручную.

Пример
$startTime = time();
$maxExecution = 60; // ограничим сами
set_time_limit(0);
while (true) {
    // Длительная операция
    if (time() - $startTime > $maxExecution) {
        echo "Превышено ручное ограничение в 60 секунд";
        break;
    }
    // ...
}
Превышено ручное ограничение в 60 секунд

Пример 3. Обработка превышения времени через register_shutdown_function

Хотя фатальную ошибку таймаута нельзя перехватить, можно зарегистрировать функцию, которая выполнится при завершении скрипта, и проверить последнюю ошибку.

Пример
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error && $error['type'] === E_ERROR && strpos($error['message'], 'Maximum execution time') !== false) {
        echo "Скрипт был прерван по таймауту после " . $error['file'] . ":" . $error['line'] . "\n";
        // Здесь можно сохранить промежуточные данные
    }
});

set_time_limit(5);
// Бесконечный цикл
while (true) {}
Скрипт был прерван по таймауту после /path/to/script.php:10

Пример 4. Комбинация ignore_user_abort и set_time_limit для фоновых задач

Если скрипт должен продолжать работу даже после того, как клиент разорвал соединение, используйте ignore_user_abort(true) и увеличьте лимит.

Пример
ignore_user_abort(true);
set_time_limit(600); // 10 минут

// Длительная обработка, клиент может закрыть страницу
$fp = fopen('/tmp/large_log.txt', 'a');
for ($i = 0; $i < 1000000; $i++) {
    fwrite($fp, "Строка $i\n");
}
fclose($fp);
echo "Запись завершена";
(клиент может не увидеть вывод, но файл будет записан полностью)

Пример 5. Изменение таймаута через .user.ini (для PHP-FPM)

На хостингах с PHP-FPM можно создать файл .user.ini в корневой директории сайта, чтобы применить настройки для всех скриптов в этой папке.

Пример
; .user.ini
max_execution_time = 200

Файл считывается автоматически при каждом запросе, перезагрузка сервера не требуется. Действует аналогично php.ini, но на уровне директории.

Пример 6. Проверка текущего лимита и изменений через ini_get

Пример
echo "Текущий лимит: " . ini_get('max_execution_time') . " секунд\n";
ini_set('max_execution_time', 90);
echo "Новый лимит: " . ini_get('max_execution_time') . " секунд\n";
Текущий лимит: 30 секунд
Новый лимит: 90 секунд

Пример 7. Настройка таймаута через консольный PHP (CLI)

В командной строке лимит выполнения обычно неограничен, но его тоже можно переопределить через аргументы или в коде.

Пример
php -d max_execution_time=120 script.php

Внутри скрипта также можно использовать set_time_limit().

Увеличение времени выполнения скрипта PHP - comments

En
Time out php (php)