Как уловить фатальную ошибку: Максимальное время выполнения 30 секунд превышено в PHP
Я играю с системой, которую я разрабатываю, и мне удалось заставить ее сделать это:
Неустранимая ошибка: превышено максимальное время выполнения на 30 секунд
Это случилось, когда я делал что-то нереалистичное, но тем не менее это могло случиться с пользователем.
Кто-нибудь знает, есть ли способ поймать это исключение? Я читал, но все, кажется, предлагают увеличить время.
Ответы
Ответ 1
Ваши единственные варианты - увеличить допустимое время выполнения (установка его на 0 делает его бесконечным, но это не рекомендуется) из script или порождает новый поток и надеется на лучшее.
Причина, по которой это не увлекательно, заключается в том, что ее не бросают. Ни одна строка кода не вызвала ошибку, скорее, PHP сказал: "Нет, простите, это слишком долго. Пора прекратить сейчас". И это имеет смысл. Представьте себе, что script с максимальным временем выполнения 30 секунд поймать эту ошибку и занять еще 30 секунд... в плохо разработанной программе, которая открывает некоторые довольно неприятные возможности для использования. Как минимум, это создаст возможности для DOS.
Ответ 2
Как насчет того, чтобы в 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);
?>
Посмотрите на следующие ссылки:
- http://www.php.net/manual/en/function.set-error-handler.php#106061
- http://www.php.net/manual/en/function.register-shutdown-function.php
Ответ 3
Это не исключение, это ошибка. Существуют важные различия между исключениями и ошибками, в первую очередь ошибки не могут быть обнаружены с помощью семантики try/catch.
PHP-сценарии построены на основе парадигмы короткого времени выполнения, поэтому PHP по умолчанию настроен так, чтобы предполагать, что если сценарий выполняется более 30 секунд, он должен быть пойман в бесконечный цикл и, следовательно, должен быть завершен. Это сделано для того, чтобы ошибочный сценарий PHP вызывал отказ в обслуживании либо случайно, либо по злому умыслу.
Однако сценарии иногда требуют больше времени выполнения, чем они выделены по умолчанию.
Вы можете попробовать изменить максимальное время выполнения, либо используя set_time_limit()
, либо изменив значение max_execution_time
в файле php.ini
, чтобы поднять предел. Вы также можете полностью снять ограничение, установив время выполнения на 0, хотя это не рекомендуется.
set_time_limit()
может быть отключено такими механизмами, как disable_functions
, поэтому он может быть недоступен для вас, также вы можете не иметь доступа к php.ini
. Если это так, то вам следует обратиться за помощью к вашему хосту.
Единственным исключением являются скрипты PHP, запускаемые из командной строки command line. В этих условиях работы PHP-скрипты могут быть интерактивными и требовать много времени для обработки данных или ожидания ввода. По этой причине не существует ограничения max_execution_time
для сценариев, запускаемых из командной строки по умолчанию.
ОБНОВЛЕНИЕ ДОБАВИТЬ: обработка ошибок PHP 7 претерпела серьезные изменения. Я считаю, что ошибки и исключения теперь являются подклассами Throwable. Это может сделать вышеупомянутое больше не релевантным для PHP7+, хотя мне нужно будет более внимательно изучить особенности того, как обработка ошибок работает сейчас, чтобы быть уверенным.
Ответ 4
Вы ничего не можете с этим поделать. но вы можете иметь изящное завершение работы с помощью 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
}
?>
Ответ 5
Да, я протестировал решение TheJanOnline. sleep() не учитывает время выполнения php, поэтому здесь находится версия WORKING с неопределенным циклом:
<?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
?>
Ответ 6
В некоторых случаях есть небольшой сложный способ обработки "Неустранимая ошибка: максимальное время выполнения 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
}
Ответ 7
Я придумал это на основе ответа @pinkal-vansia. Поэтому я не претендую на оригинальный ответ, но ответ с практическим приложением. Мне нужен был способ обновить страницу в случае таймаута. Поскольку я наблюдаю достаточное количество тайм-аутов моего cURL script, чтобы знать, что код работает, но иногда по какой-либо причине он не может подключиться к удаленному серверу или полностью прочитать обслуживаемый html, и что при обновлении проблема исчезает, Я в порядке с script, обновляя себя, чтобы "вылечить" максимальную ошибку таймаута выполнения.
<?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 секунд не слишком длинный для скребка script Я запускаю, что занимает чуть меньше, чем для извлечения данных из тех страниц, которые я соскабливаю. Иногда это происходит через несколько секунд только из-за неравномерности соединения. Зная, что время соединения, которое иногда терпит неудачу, а не script обработки, лучше не увеличивать таймаут, а просто просто обновлять страницу и повторять попытку.
Ответ 8
поместите это в начало php файла
<?php
set_time_limit(0);
РЕДАКТИРОВАТЬ 1
но сначала проверьте, нет ли такого кода:
while (1=1) {
echo '=)';
}
РЕДАКТИРОВАТЬ 2
чтобы поймать эту ошибку, посмотрите set_error_handler