it-swarm.com.ru

Тайм-аут функции в 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?

Спасибо!!

20
Mo3z

Это зависит от вашей реализации. 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
  }
}

Другой пример, где прерывание обработки IS невозможно:

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

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

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

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

9
Ray

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

// 10 minutes
pcntl_alarm( 600 );
pcntl_signal( 'SIGALRM', function() { print( "I am done!\n" ); exit( 0 ); } );

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

7
Jacques

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

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

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

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

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

и т.п.

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

5
aurora

Перед началом цикла установите переменную, которая запоминает 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.
}
?>
4
D. Strout

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

1
Recognizer

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

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";
0
user1418446