У меня есть PHP-скрипт командной строки, который запускает запрос wget, используя каждый член массива с foreach. Этот запрос wget иногда занимает много времени, поэтому я хочу установить тайм-аут для убийства скрипта, если он, например, занимает 15 секунд. У меня отключен Safemode PHP и в начале скрипта вызывается set_time_limit (15), однако он продолжается бесконечно. Обновление: спасибо Дор за это, потому что set_time_limit () не поддерживает вызовы system ().
Поэтому я пытался найти другие способы убить скрипт после 15 секунд исполнения. Однако я не уверен, можно ли проверить время запуска скрипта, когда оно находится в середине запроса wget в то же время (цикл while не работает). Может быть, разветвить процесс с помощью таймера и установить его, чтобы убить родителя через определенное количество времени?
Спасибо за любые советы!
Обновление: Ниже мой соответствующий код. $ url передается из командной строки и представляет собой массив из нескольких URL-адресов (извините за то, что вы не опубликовали это изначально):
foreach( $url as $key => $value){ $wget = "wget -r -H -nd -l 999 $value"; system($wget); }
Вы можете использовать комбинацию «–timeout» и time (). Начните с выяснения, сколько времени у вас общее, и опустите –timeout по мере запуска вашего скрипта.
Например:
$endtime = time()+15; foreach( $url as $key => $value){ $timeleft = $endtime - time(); if($timeleft > 0) { $wget = "wget -t 1 --timeout $timeleft $otherwgetflags $value"; print "running $wget<br>"; system($wget); } else { print("timed out!"); exit(0); } }
Примечание: если вы не используете -t, wget будет пытаться выполнить 20 раз, каждый из которых – время ожидания.
Вот пример кода с использованием proc_open / proc_terminate (предложение @ Josh):
$descriptorspec = array( 0 => array("pipe", "r"), 1 => array("pipe", "w"), 2 => array("pipe", "w") ); $pipes = array(); $endtime = time()+15; foreach( $url as $key => $value){ $wget = "wget $otherwgetflags $value"; print "running $wget\n"; $process = proc_open($wget, $descriptorspec, $pipes); if (is_resource($process)) { do { $timeleft = $endtime - time(); $read = array($pipes[1]); stream_select($read, $write = NULL, $exeptions = NULL, $timeleft, NULL); if(!empty($read)) { $stdout = fread($pipes[1], 8192); print("wget said--$stdout--\n"); } } while(!feof($pipes[1]) && $timeleft > 0); if($timeleft <= 0) { print("timed out\n"); proc_terminate($process); exit(0); } } else { print("proc_open failed\n"); } }
Попробуйте использовать аргумент --timeout
wget --timeout
в дополнение к set_time_limit()
.
Помните, что set_time_limit(15)
перезапускает счетчик тайм-аута с нуля, поэтому не вызывайте его внутри цикла (для вашей цели)
от man wget
:
–timeout = секунды
Установите тайм-аут сети на секунды. Это эквивалентно заданию –dns-timeout, -connect-timeout и -read-timeout, одновременно.
При взаимодействии с сетью Wget может проверять таймаут и прерывать операцию, если она занимает слишком много времени. Это предотвращает аномалии, такие как висящие чтения и бесконечные соединения. Единственный тайм-аут, включенный по умолчанию, – это 900-секундный тайм-аут чтения. Установка тайм-аута на 0 полностью отключает его. Если вы не знаете, что делаете, лучше не изменять настройки тайм-аута по умолчанию.
Все параметры, зависящие от тайм-аута, принимают десятичные значения, а также значения подсегмента. Например, 0,1 секунды является законным (хотя и неразумным) выбором таймаута. Субсекундные тайм-ауты полезны для проверки времени ответа сервера или проверки задержки сети.
EDIT: ОК. Я вижу, что ты сейчас делаешь. Вероятно, вам следует использовать proc_open вместо system
и использовать функцию time()
для проверки времени, вызывая proc_terminate, если wget tskes слишком длинный.
Вы можете направлять вывод программы wget в файл, который затем немедленно возвращается.
Также см:
Примечание. Функция set_time_limit () и директива конфигурации max_execution_time влияют только на время выполнения самого скрипта. Любое время, затрачиваемое на активность, которое происходит вне выполнения сценария, например системные вызовы с использованием system (), потоковые операции, запросы к базе данных и т. Д., Не включается при определении максимального времени выполнения сценария. Это не относится к Windows, где измеренное время реально.
Источник: set_time_limit () @ php.net