Для комментариев зарегистрироваться или войти
Либо используйте ваш Open_ID, например аккаунт гугл, яндекс или ЖЖ
 

08 ноября 2009 :Как запустить долговыполнимый php-скрипт

Технологам моей фирмы часто приходится писать php-скрипты которые требуют большого времени выполнения. Многих php-кодеров такая задача как ни странно ставит в тупик, и сводится для них к оптимизации программы, или увеличения time-limit его запуска в апаче например. Тем ни менее никакая оптимизация не поможет если вам необходимо перегенерить тысячу превьюшек к фотографиям каталога магазина. Существуют пара на мой взгляд очевидных способов запускать такие скрипты.

 

Запуск командой через SSH

Это самый быстрый способ. Скрипт запущенный в командной строке сервера выполняется гораздо быстрее чем скрипт запущенный через Apache. Это как раз особенно заметно на генерации тысячи превьюшек.

В данном случае у вас может немного измениться местоположение папок и файлов если вы ведёте в скрипте запись в файлы. Это может быть тогда когда каталог запуска скрипта не совпадает с каталогом самого скрипта. Вам может помочь добавление такой строчки в начало вашего файла.

chown(realpath(___FILE___));

Запуск через Cron

Это примерно то же что и прямым вызовом команды php в ssh. Иногда доступа к ssh хостинг может не предоставлять, иногда в ssh может быть запрещён запуск php (по совершенно непонятным причинам как на хостинге J***.ru, хотя они обещают разрешить). Но запуск скриптов через крон как правило присутствует и в нём php тоже запускается. Например когда мы скачивали главные страницы всех сайтов рунета (2000000 штук) каждый десятый сайт наровил отнять минуту на загрузку, поэтому запуск такого скрипта в ssh был затянут надолго. Скачивая по пять сайтов в секунду кроном мы смогли скачать весь рунет всего за неделю. =)

Принцип запуска приложений в кроне почти такой же как и в ssh, за одной деталью: напишите свой скрипт так чтобы он запускался в один цикл, как для ssh... после этого сделайте перед началом цикла запись в файл номера позиции на которой вы остановились, а в первой строке цикла проверку на эту позицию. Например запись позиции при скачивании рунета мы осуществляли такой функцией

// int: going to update last users counter script since aborting a write because a file is locked is not correct.
function ifile($filename,$plus=1){
        clearstatcache();
        ignore_user_abort(true);     ## prevent refresh from aborting file operations and hosing file
        if (file_exists($filename)) {
          $fh = fopen($filename, 'r+');
           while(1) {
             if (flock($fh, LOCK_EX)) {
                $buffer = chop(fread($fh, filesize($filename)));
                $buffer+=$plus;
                rewind($fh);
                fwrite($fh, $buffer);
                fflush($fh);
                ftruncate($fh, ftell($fh));
                flock($fh, LOCK_UN);
                break;
             }
          }
        }
        else {
          $fh = fopen($filename, 'w+');
          fwrite($fh, $plus);
          $buffer=$plus;
        }
        fclose($fh);
        return $buffer;
}

Использовать её нужно примерно так:

$my_position=ifile('counter.txt');
foreach($something as $i=>$tmp){
        if($i<$my_position)continue;
        /// делаем что-то c $tmp
        die();
}

Запуск через Apache

Да, да, во-многих случаях запустить скрипт через Apache быстрее чем дождаться пока выполниться крон, тем более когда нужно увидеть возвращаемые ошибки.

Принцип запуска примерно такой же как в кроне, т.е. запускать каждый этап скрипта отдельно. Если у вас есть цикл который целиком никак не влазиет в time-limit веб-сервера, но который вполне можно выполнить за несколько раз сделайте такое-же добавление к коду как для Cron выше, и после каждого выполнения действий с элементом цикла вызывайте такую функцию:

function meta_page_refresh($url,$time=0){
        if($time<0)$time=0;
        echo 'META REFRESH
                <meta http-equiv="refresh" content="'.$time.';url='.$url.'">
        ';
}

В данном случае вы можете обойтись без записи позиции в файл, а просто передавать её параметром $_GET, например так:

$i=(int)$_GET['num'];
meta_page_refresh('index.php?num='.($i+1)));

Вот и все секреты на сегодня. Следите за обновлениями через RSS.


я буду очень признательна если вы прокоментируете эту статью

Комментарии:


Чтобы оставить комментарий нужно зарегистрироваться или войти.
Либо волшебно используйте ваш логин в Google, Яндекс, рамблер или ЖЖ чтобы войти через Open_ID
Оставить комментарий как:
Гость:
Сообщение:
Подпишитесь на статьи через RSS

15 самых популярных статей: