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

Спасибо!!

Это зависит от вашей реализации. 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's no way to break out of it after a certain amount of time. return preg_replace('/pattern/', 'replace', $value); } 

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

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

Вы хотите использовать функцию 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

Вы можете попробовать выполнить это с помощью «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 и / или завиток для php поддерживает SSH / SFTP, хотя:

  • SFTP из PHP – неопределенные константы CURLOPT_PROTOCOLS и CURLPROTO_SFTP?
  • SFTP из PHP

и т.п.

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

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

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