Тайм-аут функции в 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?
Спасибо!
Ответы
Ответ 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";