PHP: echo в бесконечном цикле и "бесконечное" время выполнения скрипта
Известная "проблема" PHP - вывод всех сообщений, которые сформированы в теле цикла, только после завершения этого цикла. На самом деле это, конечно, не проблема, а однопоточное выполнение :)
Как вариант её решения, можно сделать собственную буферизацию вывода. У меня прилагаемый листинг сработал на локалхосте с Denwer.
Также пример иллюстрирует следующие моменты:
- как установить "бесконечное" время выполнение скрипта (
set_time_limit (0)
); - PHP 5.X всё равно не использует памяти более 2Гб;
- как перевести сокращения для байтовых значений PHP (P, T, G, M, K - их использует ряд настроек файла
php.ini
) в байты.
Вот код:
<?php function let_to_num($v){ //Размерности php.ini в байты $l = substr($v, -1); $ret = substr($v, 0, -1); switch(strtoupper($l)){ //нету break - это здесь верно! case 'P': $ret *= 1024; case 'T': $ret *= 1024; case 'G': $ret *= 1024; case 'M': $ret *= 1024; case 'K': $ret *= 1024; break; } return $ret; } ini_set('memory_limit','3G'); set_time_limit (0); ini_set('output_buffering','on'); ini_set('zlib.output_compression', 0); ob_implicit_flush(); //1 $n = ini_get('memory_limit'); echo 'Memory limit= '.let_to_num($n).' byte(s)<br>'. 'Time limit= '.ini_get('max_execution_time').' (0=infinite)<br>'; $a = array(); for ($i=1;;$i++) { $a[] = $i; if ($i%1000000==0) { //раз в миллион шагов $m = memory_get_usage (true); $items = count($a); echo $m.' byte(s) free after '.$items.' item(s)<br>'; //2 ob_flush(); //3 flush(); sleep(1); } } ?>
Memory limit= 3221225472 byte(s) Time limit= 0 (0=infinite) 84934656 byte(s) free after 1000000 item(s) 169082880 byte(s) free after 2000000 item(s) ... 1815085056 byte(s) free after 21000000 item(s) 1895038976 byte(s) free after 22000000 item(s) Fatal error: Out of memory (allocated 1937506304) (tried to allocate 35 bytes) in X:\home\localhost\www\1.php on line 26
Как видите, больше 22 миллионов целочисленных элементов в массиве мой PHP не осилил, если добавлять поэлементно :)
Вообще же, эксперименты показывают, что "бесконечный" (в терминах php) скрипт падает за период от нескольких часов до 7-10 дней, даже если он не пожирает память, как мой пример.
Почему - неясно, проблема, похоже, не зависит от Apache или используемой операционки.
Как вариант, если нужен "бесконечный" цикл, можно периодически запускать в cron дополнительный маленький скрипт, который будет проверять, жив ли основной скрипт и при необходимости стартовать его. Конечно, при этом возможны перерывы в работе скрипта.
Собственно, можно вообще вместо "просто скрипта" написать правильного демона на PHP. Будет работать, пока не сгорит комп :)
Можно скомпилировать php-скрипт в exe'шку и работать уже с ней.
Можно запускать без Апача, погуглите на тему
nohup php myscript.php
08.04.2016, 16:34 [7796 просмотров]