Рассматриваю алгоритм, а не конечное решение! Частенько у нас возникают задачи для длительной обработки каких либо данных. Например рассылка или пакетная обработка логов и иногда задачи вылезают даже за пределы часа (не говоря о стандарте в 30 секунд). Что можно использовать для этого : 1. писать не браузерное приложение.(наверное самое правильное). a. Недостаток в отсутствие кросс платформенности b. Нагрузка вашей машины (или машины клиента) вместо сервера. c. Использование каналов не расчитанных на подобное (часто мы или на стриме всем офисом или того хуже на модеме) d. Испоьзование непривычной среды (кому как, но к ПХП я уже прикипел) 2. запускать как CLI кроном a. Кли он и есть кли, здесь и отсутствие прямого взаимодействия с исполняемым приложением и отсутствие у запущенного приложения привычных переменных окружения. 3. запускать через exec или system неудобно, так как все равно не отпустит ваше приложение до момента окончания работы внешнего скрипта. Здесь на форуме, я увидел предложение запускать через fsockopen, в запускаемом скрипте, соответственно увеличить тайм лимит, и поставить игнорирование обрыва клиента. Поэкспериментировав вот что я получил: Что хотел: запуск скрипта по команде отсутствие зависания браузера в ожидании окончания работы длительной обработки защита от вторичного запуска во время работы предыдущего запуска скрипта защита от прекращения работы при обрыве соединения возможность мониторинга работы возможность прекратить работу до её окончания вот что получилось: Ещё раз повторю - это тестирование алгоритма а не финальный скрипт - собственно сам алгоритм и интересен был Запускаемый скрипт, с продолжительным временем работы (send.php): PHP: <?php session_start(); set_time_limit(0); ignore_user_abort(1); echo '';flush();ob_flush(); // отправить заголовки define('counts_interation',2000); if(!isset($_SESSION['stop']))$_SESSION['stop']=0; // значения по умолчанию //вариант сбора сообщение в сессии // в данном случае вывод сообщений и очистка буфера if(!empty($_SESSION['message'])){ echo implode("\r\n",$_SESSION['message'])."<hr>\r\n"; $_SESSION['message']=array(); } if($_POST['start']&&$_SESSION['start']){echo '<b>Wait we work</b>'."\r\n";} // если скрипт уже работает - сообщить об этом if($_POST['stop'])$_SESSION['stop']=1; // выставить указатель остановки работы if( !$_SESSION['start'] && $_POST['start'] ){ // не позволить приступить к работе если она уже идет $_SESSION['message'][]='script started'; // сообщаем о успешном запуске $_SESSION['start']=true; // поставить указатель о начавшейся работе (чтобы не прервали и не запустили ещё раз) for($i=0; $i < counts_interation; $i++){ if($_SESSION['stop']){$_SESSION['stop']=0;$_SESSION['message'][]='script stoped';break;} // прекратить работу по указанию // собственно сама работа echo 'i='.$i."\r\n"; $_SESSION['count']=$i.'/'.counts_interation; // собираем информацию от проделанной работе flush();ob_flush();// обязательно - сбрасываем буфер - иначе апач будет ждать окончания работы и ничего невыдаст управляющему скрипту - и тот в свою очередь будет висеть до таймаута session_write_close(); //сессию незабываем закрывать перед спячкой, а то новое соединение не откроется пока это не завершится usleep(300000); // спячка session_start(); // восстановить данные сессии } $_SESSION['start']=false; // поставить указатель о прекращенной работе } echo 'We at '.$_SESSION['count']."\r\n"; // показать чего мы достигли ?> Скрипт, который управляет, запускаемым приложением (test.php): PHP: <?php session_start(); // параметры для передачи их вызываемому скрипту $data['test_data'][]=array('name'=>'test','value'=>'uhahaha'); $data['test_data'][]=array('name'=>'test3','value'=>'uhahaha'); $data['stop']=$data['start']=0; // управляющие команды // Меню для управления echo '<a href="?set=clearExternalSession">Clear Externel Session</a> || <a href="?set=start">Start</a> || <a href="?set=stop">Stop</a> || <a href="?set=refresh">Resresh</a> '."<br>\r\n"; echo '<hr>'; //установка команд if(@$_GET['set']==='clearExternalSession')$_SESSION['external session']=''; // сбросить сид удаленного скрипта if(@$_GET['set']==='start')$data['start']=1; if(@$_GET['set']==='stop')$data['stop']=1; // функция обращения к внешнему скрипту через fsockopen function init_sock($METHOD='GET',$data=array(),&$cookie='',&$headers=''){ $data=http_build_query($data); // формируем заголовки соединения $out[]="$METHOD /catalog/send.php HTTP/1.1"; // тут я жеско указываю запускаемый скрипт , думаю разберетесь как это исправить ? $out[]="Host: 192.168.20.25"; $out[]="User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.11) Gecko/20071127 Firefox/2.0.0.11"; $out[]="Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5"; $out[]="Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3"; $out[]="Accept-Encoding: gzip,deflate"; $out[]="Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7"; $out[]="Connection: close"; if(!empty($cookie))$out[]="Cookie: $cookie"; //если у нас есть СИД для управления запущенным скриптом - ставим его if(!empty($data)){ $out[]="Content-Type: application/x-www-form-urlencoded"; $out[]="Content-length: ".strlen($data); } $out[]=''; $out[]=$data; // пердача параметров и данных для работы скрипта // приятный побочный эффект, скрипт может быть не только на вашем сервере или быть спрятаным в локальную заглушку $con=fsockopen("192.168.20.25",80,$ern,$ers,1);//открываем соединение (здесь таймаут на установку соединения) fwrite($con,implode("\r\n",$out)); // записываем заголовки $headers=$TEXT='';$fl=false;$fl_header=true; $start_time=microtime(1); // ставим точку отсчета времени while (!feof($con)) { $count_time=(microtime(1)-$start_time); // смотрим сколько времени длится соединение $mm=str_replace("\r\n","\n",fgets($con, 1024)); // зачитываем получаемые данные if($fl_header){ // отделяем заголовки от контента $headers.=$mm; // собираем заголовки $Pos=mb_strpos($headers,"Set-Cookie: "); if($Pos!==false) $cookie=substr($headers,$Pos+12,mb_strpos($headers,";",$Pos)-$Pos-12); // забираем сид if(mb_strpos($headers,"\n\n")!==false) $fl_header=false;continue; }else{ $TEXT.=$mm; // собираем контент // если соединение висит слишком долго топрекращаем сбор данных if($count_time > 0.505){ echo '<u>end by time</u>('.$count_time.")<br>\r\n";break;} // если мы получили много данных то прекращаем сбор данных if(strlen($TEXT) > 1024){ echo '<u>end by length</u>'."<br>\r\n";break;} } } fclose($con); return $TEXT; // возвращаем собранные данные } //инициализируем соединение // $_SESSION['external session'] - сид удаленной сесси - чтобы можно было управлять запущенным скриптом (типа пид получился ) // заголовки получаем по ссылке $tmp_out=init_sock('POST',$data,$_SESSION['external session'],$hh); echo '<b>out['.$_SESSION['external session'].']</b><pre>'.$hh.'>>'.$tmp_out.'<<</pre>'; выводим все на экран ?> Здесь получается что мы запускаемому приложению может ещё и определенный объем данных давать на обработку, не используя сторонние временные файлы. забыл сказать - запускаемое приложение обязательно должно периодически чтонибудь выдавать , иначе управляющий скрипт будет повисать.
браузерное приложение - это то, что выполняется в браузере, яваскрипт, например. ПХП - серверное приложение, тут даже где то ссылка ходит "на танке", там это особо подчеркивается кроссплатформенность - это зависит от языка программирования и самого кода, вполне возможно написать код на Си или Дельфи и скомпилить нужным компилятором, будет работать и на линухе и на винде. При этом доступна куда большая скорость работы. Для запуска без ожидания все довольно просто - запускается лаунчер, он создает процесс и сам завершается. Процесс работает до посинения. Лаунчер можно написать как CGI. Насчет непривычной среду - ну дело практики, иногда полезно знать что нибудь кроме ПХП
antonn - да конечно ты прав, я неправильно выразился ... имелось в виду приложение не общающиеся по стандартному каналу http ... и незадействующее силы http сервера ( хотя опять кто-нить придерется ) Вообщем я пытался продемонстрировать альтернативный подход...
Я конечно не в тему, но есть у кого опыт использования не fsockopen, а socket_connect. Интересует что более ошибка устойчиво (не зависает при ожидании соединения), и что быстрей выполняется (меньше нагрузки на процессор, память).