Как поймать фатальная ошибка: максимальное время выполнения 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