Как поймать фатальная ошибка: максимальное время выполнения 30 секунд превышен в PHP
Я играл с системой, которую я разрабатываю, и мне удалось заставить ее вызвать это:
фатальная ошибка: максимальное время выполнения 30 секунд превысила
Это произошло, когда я делал что-то нереальное, но тем не менее это могло произойти с пользователем.
кто-нибудь знает, есть ли способ поймать это исключение? Я читал вокруг, но все, кажется, предлагают увеличить разрешенное время.
8 ответов:
вы можете увеличить допустимое время выполнения (значение 0 делает его бесконечным, но это не рекомендуется) скрипт или создаст новый поток и надеяться на лучшее.
причина, по которой это не уловимо, заключается в том, что он на самом деле не брошен. Ни одна строка кода на самом деле не вызвала ошибку, а PHP сказал: "Нет, извините, это слишком долго. Пора закрываться прямо сейчас.- И это имеет смысл. Представьте себе сценарий с максимальным временем выполнения 30 секунд ловить эту ошибку и еще 30 секунд... в плохо разработанной программе это открывает некоторые довольно неприятные возможности для использования. Как минимум, это создаст возможности для DOS атаки.
Как насчет того, чтобы попробовать в качестве документации PHP (ну... по крайней мере, один из его читателей) говорят:
<?php function shutdown() { $a=error_get_last(); if($a==null) echo "No errors"; else print_r($a); } register_shutdown_function('shutdown'); ini_set('max_execution_time',1 ); sleep(3); ?>
посмотрите на следующие ссылки:
это не исключение, это ошибка. Существуют важные различия между исключениями и ошибками, в первую очередь ошибки не могут быть пойманы с помощью семантики try/catch.
PHP скрипты построены вокруг парадигмы короткого времени выполнения, поэтому PHP по умолчанию настроен на предположение, что если скрипт работает дольше 30 секунд, он должен быть пойман в бесконечный цикл и поэтому должен быть завершен. Это делается для предотвращения ошибочных PHP-скриптов, вызывающих отказ в обслуживании, либо случайно, либо по злому умыслу.
тем не менее, сценарии иногда требуется больше времени выполнения, чем они выделяются по умолчанию.
вы можете попробовать изменить максимальное время выполнения, либо с помощью
set_time_limit()
или путем изменения значенияmax_execution_time
наphp.ini
файл для повышения лимита. вы также можете полностью удалить ограничение, установив время выполнения равным 0, хотя это не рекомендуется.
set_time_limit()
может быть отключен с помощью таких механизмов, какdisable_functions
таким образом, он может быть недоступен для вас, также вы не можете иметь доступ кphp.ini
. Если оба эти случая, то вы должны связаться с вашим хозяином за помощью.одно исключение - PHP скрипты запускаются из командная строка. В этих условиях работы PHP-скрипты могут быть интерактивными и требуют длительного времени обработка данных или ожидание ввода. По этой причине нет
max_execution_time
ограничение на выполнение скриптов из командной строки по умолчанию.
ИЗМЕНИТЬ, ЧТОБЫ ДОБАВИТЬ: обработка ошибок PHP 7 была капитально отремонтирована. Я считаю, что ошибки и исключения теперь являются подклассами Throwable. Это может сделать вышеизложенное более не актуальным для PHP7+, хотя мне придется более внимательно изучить специфику работы с ошибками, чтобы быть уверенным.
вы ничего не можете с этим поделать. но вы можете иметь корректное завершение работы с помощью register_shutdown_function
<?php ini_set('display_errors', '0'); ini_set("max_execution_time",15 ); //you can use this if you know your script should not take longer than 15 seconds to finish register_shutdown_function('shutdown'); function shutdown() { $error = error_get_last(); if ($error['type'] === E_ERROR) { //do your shutdown stuff here //be care full do not call any other function from within shutdown function //as php may not wait until that function finishes //its a strange behavior. During testing I realized that if function is called //from here that function may or may not finish and code below that function //call may or may not get executed. every time I had a different result. // e.g. other_function(); //code below this function may not get executed } } while(true) { } function other_function() { //code in this function may not get executed if this function //called from shutdown function } ?>
есть немного хитрый способ обработки "фатальная ошибка: максимальное время выполнения 30 секунд превышено" как исключение в некоторых случаях:
function time_sublimit($k = 0.8) { $limit = ini_get('max_execution_time'); // changes even when you set_time_limit() $sub_limit = round($limit * $k); if($sub_limit === 0) { $sub_limit = INF; } return $sub_limit; }
в вашем коде вы должны измерить время выполнения и выдать исключение раньше, чем может быть вызвана фатальная ошибка тайм-аута. $k = 0.8-это 80% допустимого времени выполнения, поэтому у вас есть 20% времени для обработки исключения.
try{ $t1 = time(); // start to mesure time. while (true) { // put your long-time loop condition here time_spent = time() - $t1; if(time_spent >= time_sublimit()) { throw new Exception('Time sublimit reached'); } // do work here } } catch(Exception $e) { // catch exception here }
Я придумал это, основываясь на ответе @pinkal-vansia дал. Поэтому я не претендую на оригинальный ответ, но ответ с практическим применением. Мне нужен способ для обновления страницы в случае тайм-аута. Поскольку я наблюдал достаточно таймаутов моего скрипта cURL, чтобы знать, что код работает, но иногда по какой-либо причине он не может подключиться к удаленному серверу или полностью прочитать обслуживаемый html, и что после обновления проблема уходит, я в порядке со скриптом обновление себя, чтобы" вылечить " максимальную ошибку тайм-аута выполнения.
<?php //script name: scrape_script.php ini_set('max_execution_time', 300); register_shutdown_function('shutdown'); function shutdown() { ?><meta http-equiv="refresh" content="0; url=scrape_script.php"><?php // just do a meta refresh. Haven't tested with header location, but // this works fine. }
FYI, 300 секунд не слишком долго для скрипта очистки, который я запускаю, что занимает чуть меньше времени, чтобы извлечь данные из тех страниц, которые я очищаю. Иногда это происходит всего за несколько секунд только из-за неровностей соединения. Зная, что это время соединения, которое иногда терпит неудачу, а не обработка сценария, лучше не увеличивать тайм-аут, а просто автоматически обновите страницу и повторите попытку.
Да, я тестировал решение TheJanOnline. sleep() не учитывает время выполнения php, поэтому здесь работает версия с неопределенным циклом:
<?php function shutdown() { $a=error_get_last(); if($a==null) echo "No errors"; else print_r($a); } register_shutdown_function('shutdown'); ini_set('max_execution_time',1 ); while(1) {/*nothing*/} // will die after 1 sec and print error ?>
поместите это в начало php-файла
<?php set_time_limit(0);
редактировать 1
но сначала проверьте, нет ли такого кода:
while (1=1) { echo '=)'; }
редактировать 2
, чтобы поймать эту ошибку посмотри set_error_handler