партнер компании 1с-битрикс
сайт фрилансера Сергея Эстрина
Войти как пользователь
Вы можете войти на сайт, если вы зарегистрированы на одном из этих сервисов:
Универсальная галерея - модуль для битрикс
Хотя запуск долгих скриптов на php (от 5 мин и более) по разным причинам обычно считается нежелательным, в некоторых ситуациях это может выручить. Простой пример: при xml-импорте инфоблока в битриксе с 500 свойствами и 10000 элементами, стандартного максимального времени выполнения может быть недостаточно - хотя скрипт и выполняется по шагам, но может, например, зависнуть, на создании вспомогательных индексов.
[spoiler]
В данной статье рассмотрим запуск долгих php скриптов на apache+nginx и рассмотрим также ограничения браузеров.

PHP

Самое первое, что необходимо проверить - это настройки php "max_execution_time" и "session.gc_maxlifetime" (максимальное время выполнения скрипта и время сессии соответственно). Ее можно установить из htaccess (параметры устанавливаются в секундах):

php_value max_execution_time 2400

php_value session
.gc_maxlifetime 2400
а также непосредственно из php скрипта:

set_time_limit(2400);

ini_set('session.gc_maxlifetime'2400);
или, конечно же, из php.ini

NGINX

Однако, даже если установить большое значение max_execution_time, при установленном nginx, если время еще не истекло, вы можете получить сообщение об ошибке подобное этому:

504 Gateway Timeout error using Nginx


Данную ситуацию можно исправить, отредактировав файл конфигурации nginx (на системах Debian находится здесь - /etc/nginx/nginx.conf):

proxy_connect_timeout 2400;

proxy_send_timeout 2400;
proxy_read_timeout 2400;

Ограничения браузера

Но и это еще не все. У браузеров также есть свои ограничения по времени на получение страниц и у разных браузеров они отличаются. Но это также поправимо, и проще всего эта настройка меняется в браузере Mozilla Firefox: нужно зайти в расширенные настройки введя в адресной строке "about:config", затем найти по поиску значение "network.http.connection-timeout", в котором, как и везде, можно установить значение максимального времени получения страницы в секундах.

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


Для тестирования описанных мной настроек, я приведу здесь два скрипта - простой запуск страницы и получение с использованием ajax (это может быть важно, т.к. настройки браузера могут отличаться для получения простых страниц и средствами XHR).

Простой скрипт:

<?


$ts_start time();

$cur_sec 0;

while(
true) {
   
   
$seconds time() - $ts_start;
   
   if(
$seconds%20==&& $cur_sec!=$seconds) {
      echo 
$seconds."<br />";
      
$cur_sec $seconds;
   }
   
   if(
$seconds>=2350)
      break;
   
}


Скрипт с применением ajax:

<?

if(
array_key_exists("ajax_test",$_REQUEST) && $_REQUEST["ajax_test"]=="Y") {
   
$ts_start time();
   
$cur_sec 0;
   while(
true) {
      
$seconds time() - $ts_start;
      if(
$seconds%20==&& $cur_sec!=$seconds) {
         echo 
$seconds."<br />";
         
$cur_sec $seconds;
      }
      if(
$seconds>=30)
         break;
   }
   die();
}
?><html>
<head><title>time limit test</title></head>
<body>
<a href="javascript:window.start_ajax_test();">Start ajax test</a> <span id="counter"></span>
<div id="container" style="border: 1px solid green"></div>
<script>
window.is_send = false;
window.start_ajax_test = function() {
   if(window.is_send)
      return false;
   document.getElementById('container').innerHTML = 'Loading...';
   window.is_send=true;
   window.counter_start = new Date();
   window.counter = setInterval(function(){
      var end = new Date();
      secondsOpen = Math.floor((end - window.counter_start) / 1000);
      document.getElementById('counter').innerHTML = secondsOpen + ' seconds';
   }, 250);
   window.ajax_request(
      '<?=$_SERVER['REQUEST_URI']?>',
      'POST',
      function(response_text) {
         window.is_send=false;
         document.getElementById('container').innerHTML = response_text;
         clearInterval(window.counter);
         document.getElementById('counter').innerHTML += " total";
      },
      { 'ajax_test' : 'Y' }
   );
};
window.ajax_request = function(url, requestType, callback, arParams) {
   var xhr;
   var ajax_params = function(arParams, prefix) {
      var str = [];
      for(var p in arParams) {
         if (arParams.hasOwnProperty(p)) {
            var k = prefix ? prefix + "[" + p + "]" : p, v = arParams[p];
            str.push(typeof v == "object" ?
               ajax_params(v, k) :
               encodeURIComponent(k) + "=" + encodeURIComponent(v));
         }
      }
      return str.join("&");
   }
   if (window.XMLHttpRequest) {
      xhr = new XMLHttpRequest();
   } else {
      var protocols = ['MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP'];
      for (var pc = 0; pc < protocols.length; pc++) {
         try {
            xhr = new ActiveXObject(protocols[pc]);
            break;
         } catch(e) {}
      }
   }
   xhr.onreadystatechange = function() {
      if(xhr.readyState==4)
      {
         callback(xhr.responseText);
         xhr = null;
      }
   };
   var data = ajax_params(arParams);
   if (requestType.toUpperCase() === 'GET') {
      if (data.length > 0)
         url += (url.indexOf('?') == -1?'?':'&') + data;
      xhr.open('GET', url, true);
      xhr.send("");
   } else if (requestType.toUpperCase() === 'POST') {
      xhr.open('POST', url, true);
      xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
      xhr.send(data);
   }
};
</script>
</body>
</html>

Чтобы оставить сообщение, авторизуйтесь, или войдите с помощью: