Подтвердить что ты не робот

Тайм-аут функции в PHP

Есть ли способ тайм-аута функции? У меня есть 10 минут, чтобы выполнить работу. Задание включает цикл for, вот пример:

<?php
foreach($arr as $key => $value){
   some_function($key, $value); //This function does SSH and SFTP stuff
}
?>

$arr имеет 15 элементов, а some_function() иногда может занимать более 1 минуты. Фактически, когда его повесили 5 минут.

Есть ли способ, с помощью которого я могу отключить вызов функции и перейти к следующему элементу в $arr?

Спасибо!

4b9b3361

Ответ 1

Это зависит от вашей реализации. 99% функций в PHP блокируют. Значение обработки не будет продолжаться до тех пор, пока текущая функция не будет завершена. Однако, если функция содержит цикл, который вы можете добавить в свой собственный код, чтобы прервать цикл после выполнения определенного условия.

Что-то вроде этого:

foreach ($array as $value) {
  perform_task($value);
}

function perform_task($value) {
  $start_time = time();

  while(true) {
    if ((time() - $start_time) > 300) {
      return false; // timeout, function took longer than 300 seconds
    }
    // Other processing
  }
}

Еще один пример, когда прерывание обработки невозможно:

foreach ($array as $value) {
  perform_task($value);
}

function perform_task($value) {
    // preg_replace is a blocking function
    // There no way to break out of it after a certain amount of time.
    return preg_replace('/pattern/', 'replace', $value);
}

Ответ 2

PHP однопоточный... вам нужно использовать способность вашей ОС для разблокировки другого процесса.

Единственный способ, которым я знаю, как это сделать, - это выполнить команду exec, чтобы отменить другой полный процесс. Поместите нужный материал в отдельный script, вызовите exec на script, а затем сразу же спящий на 10 минут. Если через 10 минут процесс все еще работает, убейте его. (вы должны иметь его PID, заставив команду запустить новый php-код в фоновом режиме, получив его через командную строку и вернув его из команды exec).

Ответ 3

Вам нужно использовать функцию pcntl_alarm, которая будет запускать сигнал SIGALRM по таймауту.

Например:

// 10 minutes
pcntl_alarm( 600 );
pcntl_signal(SIGALRM, function() { print( "Timed-out!\n" ); exit( 0 ); });

Пожалуйста, смотрите здесь руководство по PHP для получения дополнительной информации об этом: http://php.net/manual/en/function.pcntl-alarm.php

Ответ 4

Вы можете попробовать выполнить это с помощью "curl". Curl - из PHP - в основном используется для работы с HTTP/FTP, но он поддерживает множество других протоколов, включая ssh/sftp. Я никогда не делал что-то связанное с ssh/sftp с помощью curl, поэтому я не могу дать никаких дополнительных советов, но вы можете найти дополнительную информацию здесь, в stackoverflow или где-то еще.

Существует опция "CURLOPT_TIMEOUT", которую вы можете использовать для настройки тайм-аута для вашего запроса (там также есть опция "CURLOPT_CONNECTTIMEOUT" ). Вы даже можете указать таймауты в миллисекундном разрешении (CURLOPT_TIMEOUT_MS/CURLOPT_CONNECTTIMEOUT_MS).

В любом случае: для cronjob я бы рекомендовал использовать дополнительный "файл блокировки", который записывает ваш script при его запуске и удаляет, когда он закончен. Вы можете проверить этот файл блокировки в своем script, поэтому, если cron запускает ваш script до завершения последнего запуска, вы можете просто выйти из script без каких-либо дальнейших действий. Это гарантирует, что ваш script не будет выполняться несколько раз параллельно.

Вы также можете найти больше в параметрах CURL и CURL в документации PHP:

Вы должны убедиться, что ваш установленный libcurl и/или завиток для php поддерживает SSH/SFTP, хотя:

и др.

Надеюсь, что это поможет...

Ответ 5

Перед запуском в цикл установите переменную, которая запоминает time(). В конце каждой итерации проверьте, превышает ли текущий time() более 60 секунд. Если да, break. Например:

<?php
$startTime=time();
foreach($arr as $key => $value){
    some_function($key, $value); //This function does SSH and SFTP stuff
    if (time()-$startTime>60) break; //change 60 to the max time, in seconds.
}
?>

Ответ 6

Посмотрите set_time_limit. Теперь сама функция действительно не нужна, потому что она учитывает только время выполнения, то есть 5 секунд в реальной жизни может быть всего лишь 0,2 секунды исполнения. Но причина для просмотра ссылки - это комментарии. Там пара решений, которые пользователи разместили.

Ответ 7

Для тех из вас, кто находится в командной строке, посмотрите, как прерывается сон:

echo date("H:i:s\n");
pcntl_signal(SIGALRM ,function($signal){
echo "arghhh! i got interrupted \n";
},true);

pcntl_alarm(3);
sleep(20);
pcntl_signal_dispatch();


echo date("H:i:s\n");

pcntl_alarm(3);
sleep(20);

echo date("H:i:s\n");

pcntl_signal_dispatch();
echo "end\n";