Нон-стоп работа без крона

Тема в разделе "PHP", создана пользователем dig555, 2 июн 2009.

Статус темы:
Закрыта.
Модераторы: latteo
  1. dig555

    dig555

    Регистр.:
    22 июн 2007
    Сообщения:
    362
    Симпатии:
    148
    Есть парсер. Неважно чего. :-] Работать должен длительное время. Нужно после того как я его закинул на сервак и запустил, иметь возможность, выключить свой комп и идти спать. А скрипт пусть работает на сервере до победного конца. Я знаю точно, что возможно. Но не знаю как :)
    Буду благодарен любым ссылкам на примеры/мануалы/вашим советам. Ниже пример парсера вордстата, который был написан для меня года полтора назад. В нём эта фишка реализована. Похоже без AJAX тут не обойтись?
    PHP:
    if ((STATUS=='BUSY')||(STATUS=='DONE')) {
        
    tpl_exe(TPL_HEAD);
        
    tpl_exe(TPL_AJAX,array('action'=>$_SERVER['PHP_SELF']));
        
    tpl_exe(TPL_TAIL);
        return;
    }
    Полностью:
    PHP:
    <?php
    header
    ('Connection: Close');
    header('Cache-Control: no-cache');
    header('Pragma: nocache');
    header('Content-Type: text/html;charset=windows-1251');
    #### conf
    set_time_limit(0);
    ignore_user_abort(true);
    setlocale(LC_ALL,'ru_RU.CP1251');
    define('STATUS_FILE','./xparser.st');
    define('PROXYLIST','./proxylist.txt');
    define('BADWORDS','./badwords.txt');
    define('LETTERS','0-9a-zA-ZабвгдеёжзийклмнопрстуфхцчшщъыьэюяАБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ');
    define('URL','http://wordstat.yandex.ru/advq?rpt=ppc&key=&shw=1&tm=&checkboxes=&text={$WORD}&regions_text=%C2%F1%E5&regions=');
    define('NEWDIRPERMS',0744);
    define('STATUSUPDATERATE',10000); # частота обновления статуса в мс. для ie ставить не меньше 10000. опера и фокс нормально работают при меньших значениях
    #### conf
    function get_status() {
        return 
    file_get_contents(STATUS_FILE);
    }
    function 
    set_status$s) { # (IDLE|BUSY|DONE)|*EXTRA*
        
    $f fopen(STATUS_FILE,'w');
        
    fputs($f,$s);
        
    fflush($f);
        
    fclose($f);
    }
    function 
    set_status_busy$i$total) {
        
    set_status('BUSY|'.$i.'~'.$total);
    }
    function 
    x_headers$s) {
        
    header('Content-Length: '.strlen($s));
        echo 
    $s;
    }
    ###### tpl
    define('TPL_HEAD','<html>
    <head>
    <style>
    * {
        font-family: Tahoma;
        font-size: 10pt;
        color: black;
    }
    input, textarea {
        background:color: white;
    }
    input.b, textarea {
        border: 1px solid #906090;
    }
    div.e {
        color: yellow;
        background-color: red;
        margin: -20px -20px 0 -20px;
        padding: 10px;
    }
    </style>
    </head>
    <body marginheight=0 marginwidth=0 leftmargin=0 topmargin=0>
    <table border=0 width=100% height=100% cellpadding=0 cellspacing=0><tr><td align=center>
    <table border=1 cellpadding=20 cellspacing=0><tr><td>
    '
    );
    define('TPL_TAIL','</td></tr></table>
    </td></tr></table>
    </body>
    </html>'
    );
    define('TPL_FORM','
    <script language=javascript>
    function redir() {
        setTimeout("document.location=\'${action}\'",1000);
        return true;
    }
    </script>
    <form action="{$action}" method=post onsubmit="return redir()">
    <input type=hidden name=action value=start />
    <table border=0 cellpadding=2 cellspacing=0>
    <tr><td colspan=2><b>Параметры парсера</b></td></tr>
    <tr><td valign=top>Слова для парсинга</td><td><textarea style="width:300px;height:100px;" name=words>{$words}</textarea></td></tr>
    <tr><td>Глубина парсинга</td><td><input type=text style="width:30px;" class=b name=limit value="{$limit}" /> страниц</td></tr>
    <tr><td>Метод обхода капчи</td><td><input type=radio name=acaptcha id=asleep value=sleep {$acaptcha_sleep} /> <label for=asleep>sleep( )</label><br /><input type=radio name=acaptcha id=aproxy value=proxy {$acaptcha_proxy} /> <label for=aproxy>прокси</label></td></tr>
    <tr><td><label for=afilter>Чистить плохие слова?</label></td><td><input type=checkbox name=filter id=afilter {$filter} /></td></tr>
    <tr><td><label for=ashuffle>Перемешивать кеи?</label></td><td><input type=checkbox name=shuffle id=ashuffle {$shuffle} /></td></tr>
    <tr><td>Разбить результат по</td><td><input type=text style="width:40px;" class=b name=page value="{$page}" /> кеев</td></tr>
    <tr><td>Сохранять в каталог</td><td><input type=text style="width:100px;" class=b name=path value="{$path}" /></td></tr>
    <tr><td colspan=2 align=right><input type=submit style="width:40px;" class=b value=Go /></td></tr>
    </table>
    </form>
    '
    );
    define('TPL_ERROR','<div class=e>{$msg}</div>');
    define('TPL_AJAX','
    <script language=javascript src="ajax.js"></script>
    <script language=javascript>
    var __done;
    var __c = 0;
    function __parse( s) {
        if (s.substr(0,11)=="javascript:") {
            eval(s.slice(11));
            return false;
        }
    /*    __c++;
        document.getElementById("jjj").innerHTML = s.slice(5)+" (a="+__c+")";
        return false;*/
        return true;
    }
    var ao;
    function refresh() {
        ao.sndReq("post","{$action}","action=status");
        if (!__done) {
            setTimeout("refresh()",'
    .STATUSUPDATERATE.');
        }
    }
    window.onload = function() {
        __done = false;
        ao = new AjaxObject101();
        ao.funcDone = __parse;
        refresh();
    }
    </script>
    <center><b>Процесс пошел</b><br /><br /><div id="jjj">***</div></center>
    '
    );
    function 
    tpl_exe$tpl$args=false) {
        if (
    $args!==false) {
            
    extract($args);
        }
        echo eval(
    'return "'.str_replace('"','\"',$tpl).'";');
    }
    ###### tpl
    function wrap_msg$s) {
        
    tpl_exe(TPL_HEAD);
        echo 
    $s;
        
    tpl_exe(TPL_TAIL);
        return 
    0;
    }
    function 
    translit($cyr_str) {
        
    $razd="-";
        
    $cyr_str=strtolower($cyr_str);
        
    $tr = array (
            
    "А"=>"a","Б"=>"b","В"=>"v","Г"=>"g",
            
    "Д"=>"d","Е"=>"e","Ж"=>"zh","З"=>"z","И"=>"i",
            
    "Й"=>"y","К"=>"k","Л"=>"l","М"=>"m","Н"=>"n",
            
    "О"=>"o","П"=>"p","Р"=>"r","С"=>"s","Т"=>"t",
            
    "У"=>"u","Ф"=>"f","Х"=>"h","Ц"=>"c","Ч"=>"ch",
            
    "Ш"=>"sh","Щ"=>"sch","Ъ"=>"","Ы"=>"y","Ь"=>"",
            
    "Э"=>"e","Ю"=>"u","Я"=>"ya","а"=>"a","б"=>"b",
            
    "в"=>"v","г"=>"g","д"=>"d","е"=>"e","ж"=>"zh",
            
    "з"=>"z","и"=>"i","й"=>"y","к"=>"k","л"=>"l",
            
    "м"=>"m","н"=>"n","о"=>"o","п"=>"p","р"=>"r",
            
    "с"=>"s","т"=>"t","у"=>"u","ф"=>"f","х"=>"h",
            
    "ц"=>"c","ч"=>"ch","ш"=>"sh","щ"=>"sch","ъ"=>"",
            
    "ы"=>"y","ь"=>"","э"=>"e","ю"=>"u","я"=>"ya"" " => $razd
        
    );
        
    $textstrtr($cyr_str$tr);
        
    $text=preg_replace("/[^a-z0-9_ -]+/"""$text);
        return 
    $text;
    }
    function 
    rulat($words) { 
        
    $rus "АаВЕеКкМНОоРрСсТХх"
        
    $eng "AaBEeKkMHOoPpCcTXx"
        return 
    strtr($words,$eng,$rus); 

    function 
    array_exclude( &$a$i$n) {
        for (
    $j=$i+1$j<$n$j++) {
            
    $a[$j-1] = $a[$j];
        }
    }
    $x explode('|',get_status(),2);
    define('STATUS',$x[0]);
    define('STATUS_MSG',$x[1]);
    if (isset(
    $_POST['action'])) {
        switch (
    $_POST['action']) {
            case 
    'start':
                if (
    STATUS!=='IDLE') {
                    
    header('Location: '.$_SERVER['PHP_SELF']);
                    return;
                }
                
    $words trim(preg_replace('/[^'.LETTERS.']+/',' ',$_POST['words']));
                
    $words array_unique(explode(' ',$words));
                
    $words implode(' ',$words);
                
    $limit = (int)$_POST['limit'];
                
    $acaptcha $_POST['acaptcha'];
                
    $filter = isset($_POST['filter']);
                
    $shuffle = isset($_POST['shuffle']);
                
    $page = (int)$_POST['page'];
                
    $path trim($_POST['path']);
                
    $fs = array();
                if (!
    $words) {
                    
    $fs[] = 'Укажите слова для парсинга';
                }
                if (
    $limit<=0) {
                    
    $fs[] = 'Укажите глубину парсинга';
                }
                if (
    $filter&&!file_exists(BADWORDS)) {
                    
    $fs[] = 'Не найден файл с плохими словами';
                }
                if ((
    $acaptcha=='proxy')&&!file_exists(PROXYLIST)) {
                    
    $fs[] = 'Не найден файл со списком прокси';
                }
                if (
    $page<=0) {
                    
    $fs[] = 'Укажите размер разбиения результата';
                }
                
    $path str_replace('\\','/',$path);
                if (
    substr($path,-1,1)!=='/') {
                    
    $path .= '/';
                }
                if (
    file_exists($path)&&(!is_dir($path)||!is_writable($path))) {
                    
    $fs[] = 'Нет доступа к каталогу';
                }
                if (!
    sizeof($fs)&&!file_exists($path)) {
                    if (!
    mkdir($path,NEWDIRPERMS)) {
                        
    $fs[] = 'Не могу создать каталог';
                    }
                }
                if (
    sizeof($fs)) {
                    
    tpl_exe(TPL_HEAD);
                    
    tpl_exe(TPL_ERROR,array('msg'=>implode('<br />',$fs)));
                    
    tpl_exe(TPL_FORM,array(
                        
    'action' => $_SERVER['PHP_SELF'],
                        
    'words' => $words,
                        
    'limit' => $limit,
                        
    'acaptcha_sleep' => $acaptcha=='sleep'?'checked':'',
                        
    'acaptcha_proxy' => $acaptcha=='proxy'?'checked':'',
                        
    'filter' => $filter?'checked':'',
                        
    'shuffle' => $shuffle?'checked':'',
                        
    'page' => $page,
                        
    'path' => $path
                    
    ));
                    
    tpl_exe(TPL_TAIL);
                    return;
                }
                
    $words explode(' ',$words);
                
    $words_total sizeof($words);
                
    $word_count 0;
                
    set_status_busy(0,$words_total);
                
    $RZ = array();
    if (
    $filter) {
                
    $badwords strtolower(preg_replace('/\s+/',' ',trim(file_get_contents(BADWORDS))));
                
    $badwords explode(' ',$badwords);
                
    $badwords array_flip($badwords);
    }
    if (
    $acaptcha=='proxy') {
                
    $proxylist preg_replace('/\s+/',' ',trim(file_get_contents(PROXYLIST)));
                
    $proxylist explode(' ',$proxylist);
                
    $proxies sizeof($proxylist);
    }
                foreach (
    $words as $w) {
                    
    set_status_busy($word_count,$words_total);
                    
    $word_count++;
                    
    $RZ[$w] = array(
                        
    'paged' => 0,
                        
    'grabbed' => 0,
                        
    'accepted' => 0
                    
    );
                    
    $url str_replace('{$WORD}',urlencode($w),URL);
                    
    $buf = array();
    for ( 
    $step=0$step<$limit$step++) { # by pages
                    
    $RZ[$w]['paged']++;
    if (
    $acaptcha=='sleep')    {
                    
    sleep(rand(5,15));
    }
                    do {
                        
    $httpok true;
                        
    $ch=curl_init($url);
    if (
    $acaptcha=='proxy') {
                        
    $proxy rand(0,$proxies-1);
                        
    curl_setopt($chCURLOPT_PROXY$proxylist[$proxy]);
    }
                        
    curl_setopt($chCURLOPT_HEADER0);
                        
    curl_setopt($chCURLOPT_RETURNTRANSFER1);
                        
    curl_setopt($chCURLOPT_USERAGENT"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)");
                        
    curl_setopt($chCURLOPT_CONNECTTIMEOUT10);
                        
    curl_setopt($chCURLOPT_TIMEOUT10); 
                        
    curl_setopt($chCURLOPT_REFERER"http://yandex.ru");
                        
    $content=curl_exec($ch);
    if (
    $acaptcha=='proxy') {
                        if (
    curl_errno($ch)) {
                            
    $httpok false;
                            
    array_exclude($proxylist,$proxy,$proxies);
                            
    $proxies--;
                        }
    }
                        
    curl_close($ch);
                    } while (!
    $httpok);
                    
    $pos strpos($content,"Что еще");
                    if (
    $pos !== false) {
                        
    $content substr($content,0,$pos);
                    }
                    
    $RZ[$w]['grabbed'] += preg_match_all('/tm=">(['.LETTERS.' ]+)<\/a>/',$content,$matches);
                    foreach (
    $matches[1] as $v) {
                        
    $is_ok true
    if (
    $filter) { # filter bad words
                        
    $s explode(' ',$v);
                        foreach (
    $s as $t) {
                            
    $tl strtolower($t);
                            if (isset(
    $badwords[$tl])||isset($badwords[rulat($tl)])) { 
                                
    $is_ok false
                                break;
                            }
                        }
    }
                        if (
    $is_ok) {
                            
    $buf[] = $v;
                        }
                    }
                    if (
    preg_match('/<a href="(\/advq\?[^"]+)">следующая/',$content,$match)) {
                        
    $url 'http://wordstat.yandex.ru'.str_replace('&amp;','&',$match[1]);
                    } else {
                        break; 
    # no more pages
                    
    }
    }
                    
    $RZ[$w]['accepted'] = sizeof($buf);
                    if (
    $z=sizeof($buf)) {
    if (
    $shuffle) { # shuffle the keys grabbed
                        
    for ($i=1$i<$z$i++){
                            
    $a rand(0,$z-1);
                            
    $b rand(0,$z-1);
                            
    $ta $buf[$a];
                            
    $tb $buf[$b];
                            
    $buf[$a] = $tb;
                            
    $buf[$b] = $ta;
                        }
    }
                        
    $buf array_chunk($buf,$page);
                        
    $i 0;
                        foreach (
    $buf as $x) {
                            
    $f fopen($path.translit($w).'-'.(++$i).'.txt','w');
                            
    fputs($f,implode("\n",$x));
                            
    fclose($f);
                        }
                    }
                }
                
    $total_grabbed 0;
                
    $total_accepted 0;
                foreach (
    $RZ as $x) {
                    
    $total_grabbed += $x['grabbed'];
                    
    $total_accepted += $x['accepted'];
                }
                
    set_status('DONE|Обработано '.$words_total.' слов\nВытянуто '.$total_grabbed.' кеев\nСохранено (в каталог '.$path.') '.$total_accepted.' кеев');
                return;
            case 
    'status':
                if (
    STATUS=='BUSY') {
                    list(
    $a,$b) = explode('~',STATUS_MSG);
                    
    x_headers('jjj=>выполнено '.$a.'/'.$b.' ('.(int)(100*$a/$b).'%)');
                    return;
                }
                if (
    STATUS=='DONE') {
                    
    set_status('IDLE|');
                    
    x_headers('javascript:__done=true;alert("'.STATUS_MSG.'");document.location="'.$_SERVER['PHP_SELF'].'";');
                    return;
                }
                return;
            case 
    'stop':
                if (
    STATUS!=='BUSY') {
                    return;
                }
                return;
        }
    }
    if ((
    STATUS=='BUSY')||(STATUS=='DONE')) {
        
    tpl_exe(TPL_HEAD);
        
    tpl_exe(TPL_AJAX,array('action'=>$_SERVER['PHP_SELF']));
        
    tpl_exe(TPL_TAIL);
        return;
    }
    tpl_exe(TPL_HEAD);
    tpl_exe(TPL_FORM,array(
        
    'action' => $_SERVER['PHP_SELF'],
        
    'words' => '',
        
    'limit' => '1',
        
    'acaptcha_sleep' => 'checked',
        
    'acaptcha_proxy' => '',
        
    'filter' => '',
        
    'shuffle' => '',
        
    'page' => '1000',
        
    'path' => './'
    ));
    tpl_exe(TPL_TAIL);
    ?>
     
  2. PomanoB

    PomanoB Писатель

    Регистр.:
    30 май 2009
    Сообщения:
    5
    Симпатии:
    3
    set_time_limit(0); - устанавливает выполнение скрипта без ограничения по вермени
    ignore_user_abort(true); устанавливает игнорировать разрыв соединения пользователем

    Результаты лучше всего писать в файл
     
    dig555 нравится это.
  3. ZCFD

    ZCFD

    Регистр.:
    16 янв 2008
    Сообщения:
    989
    Симпатии:
    437
    set_time_limit(0) -- ток тут дело в том что хостеры фиг тебе дадут это сделать
    можешь попробовать
    110mb.com бесплатный там нет ограничения по времени

    АЯКС -- а где он у тебя работать будет, если ты комп выключишь ? )))

    я бы предложил такой вариант -- при запуске создавать и блокировать файл-флаг
    и запуск повесить на частозапрашиваемый объект ( картинка на каком нибудь сайте, или ава)
    при вызове скрипта проверять наличие флага и то что он залочен
    залочен -- все работает , выходим
    не залочен -- скрипт остановился, запускаем его по новой

    идея ясна ?
     
    dig555 нравится это.
  4. nik0tin

    nik0tin

    Регистр.:
    29 авг 2007
    Сообщения:
    320
    Симпатии:
    56
  5. dig555

    dig555

    Регистр.:
    22 июн 2007
    Сообщения:
    362
    Симпатии:
    148
    Ясна. :) Только проблема не в том, что крона нет. А в том, что я не хочу его использовать. У меня свой VPS. Так что проблемы с хостингами меня не волнуют. :-] set_time_limit(0) то работает, но скрипт становится всё равно минут через 10. Попробую поковырять php.ini. Файл-флаг сделать неплохо. Если туда записывать статус выполнения, и если он не изменился за минуту, то запускать скрипт по новой. Но это опять крон, внешние файлы, или ещё какая-то хрень ))
    Спасибо, но повторюсь, что крон у меня есть. Но чего-то мне с ним связываться не хочется абсолютно. :)
     
  6. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    У тебя свой VPS - юзай для этих целей PHP CLI. Там хоть демонов вешай.
     
  7. vivid

    vivid Постоялец

    Регистр.:
    13 апр 2009
    Сообщения:
    143
    Симпатии:
    18
    реализовать что-то типа следующего: результаты работы скрипта отдавать в таблицу либо в файлик (а по запросу скрипта чтоб отдавалось содержимое наработанное долгой работой скрипта), либо в меил.

    на php всё таки отсутствует понятие сервера приложений. но можно вызвать подчиненный скрипт, который будет вызван, например, вызовом system("php script.php > file.txt"), а если file.txt что-то содержит, т.е результаты работы, то они должны быть выведены.

    ну а если результат работы не просто текст, а что-то посложнее, то это посложнее можно сериализовать прямо в файлик.
     
  8. tarantas

    tarantas Постоялец

    Регистр.:
    22 мар 2008
    Сообщения:
    75
    Симпатии:
    14
    Если сервер апач :

    /usr/local/apache/conf/extra/httpd-default.conf

    Измени параметр Timeout на 86400 и рестартани апач.

    Либо, если нет возможности, посмотри функцию apache_reset_timeout()
     
  9. ximix

    ximix Прохожие

    $arg=$argv[1];
    system('/usr/local/bin/php /path/to/script/name.php '.$arg.' > /dev/null 2>&1 &');
    в зависимости от никса (синтаксиса утили ps) можно пробивать наличие процесса и его загрузку. т.е. можно выловить ситуации, когда скрипт начал жрать 99%.
    system('ps -auxw | grep /usr/local/bin/php | gawk \' { print $3}\' > ps.log &');
    опятьже без претензии на лучший вариант. главное функциональность.
     
  10. PHP_Master

    PHP_Master

    Регистр.:
    3 фев 2008
    Сообщения:
    2.647
    Симпатии:
    591
    Парни вы очумели?
    Какие "Timeout на 86400 и рестартани апач" и "system('/usr/local/bin/php /path/to/script/name.php '.$arg.' > /dev/null 2>&1 &');"? :eek:

    Есть CLI, его для таких целей и создавали.
     
Статус темы:
Закрыта.