Вопрос по php, function, foreach, timeout – Тайм-аут функции в PHP

20

Есть ли способ отключить функцию? У меня есть 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?

Спасибо!!

некоторые вопросы: что ограничивает вас 10 минутами? не имеет значения, выполняются ли задания ssh / sftp или нет? и можете ли вы обойти это ограничение, используя какую-то очередь? aurora
Это скрипт crontab, который запускается каждые 10 минут. Он проверяет состояние серверов и обновляет базу данных. Если я не получаю ответ в течение 1 минуты, я устанавливаю этот медленный сервер ... Mo3z

Ваш Ответ

7   ответов
1

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

4

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.
}
?>
Спасибо Дэвид за ваш ответ. Мне не нужно прерывать цикл for, мне нужно прерывать функцию some_, если это занимает больше минуты. Mo3z
17

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

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

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's no way to break out of it after a certain amount of time.
    return preg_replace('/pattern/', 'replace', $value);
}
та же проблема здесь, та же техника.
Спасибо, Майк, но у меня есть some_function, или execute_task - это основная функция, и я пытаюсь избежать изменения основного метода. Mo3z
Путь по маршруту: создание нового сценария example.php и вызов этого сценария в some_function и определение set_time_limit ... логика some_function будет выполнена в example.php .. Mo3z
9

ОС для форкирования другого процесса.

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

Не весь PHP не является многопоточным
5

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

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

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

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

http://www.php.net/manual/en/function.curl-setopt.php http://www.php.net/manual/en/book.curl.php

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

SFTP from PHP - undefined constant CURLOPT_PROTOCOLS and CURLPROTO_SFTP? SFTP from within PHP

и т.п.

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

7

которая будет запускать сигнал 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

Вроде работает только сsleep() функция.curl_exec() а такжеfile_get_contents() К сожалению, время ожидания этого решения не истекло.
Вот полная реализация:gist.github.com/avalanche123/3085581
0

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

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

Похожие вопросы