Приветствую всех. Передо мной стоит задача организовать регулярную переиндексацию сайта, которая должна выполняться в фоновом режиме, когда-нибудь ночью.
Пошарил в гугле, нашел примеры и документацию, набросал вот такой скрипт:
Скрипт тестировался из командной строки, т.е. проблем с time_limit'ами вроде быть не должно.
Теперь о проблемах.
Проблема №1. После переиндексации этим скриптом поиск перестает нормально работать. На запрос вида "электрочайник" выдается пустой результат, хотя в каталоге этих электрочайников вагон. При этом, если переиндексировать сайт через админку, с теми же настройками, то поиск прекрасно находит эти самые электрочайники.
Проблема №2. Если верить документации, то установка шага ($max_execution_time) в ноль заставляет функцию ReIndexAll проиндексировать все элементы за один шаг. При этом индексируется 1885 документов. Но если поставить ненулевой шаг (например 60 или 10000), то индексируется 3867 документов. Нахожу этот момент довольно странным.
Далее, при установленном ненулевом шаге происходит следующее: если все делается через админку, то процесс длится минуты 3, и поиск работает отлично. Если же индексация делается скриптом из консоли, то процесс занимает около 15 минут, и поиск ищет очень плохо.
Буду очень рад, если кто-нибудь объяснит мне возможные причины такого поведения и укажет на мои ошибки.
Чем дальше, тем интереснее. Поставил max_execution_time = 10000 и запустил тот же самый скрипт в браузере. Пользователь — не админ, даже не авторизован. В итоге время работы скрипта оказалось меньше, чем при запуске через консоль, и поиск стал работать нормально.
Евгений Задорин пишет: Проблема №1. После переиндексации этим скриптом поиск перестает нормально работать. На запрос вида "электрочайник" выдается пустой результат, хотя в каталоге этих электрочайников вагон. При этом, если переиндексировать сайт через админку, с теми же настройками, то поиск прекрасно находит эти самые электрочайники.
Возможно, есть какая-то разница в настройках локали для веб-сервера и для консоли.
h.diver пишет: Попробуйте запускать через /usr/bin/php -f Или можно запустить от пользователя веб-сервера, преварительно дав ему права на исполнение скрипта.
К сожалению, не прокатило. Пробовал запускать от имени root'a, пробовал от имени пользователя сервера (www-data), безрезультатно.
Цитата
Возможно, есть какая-то разница в настройках локали для веб-сервера и для консоли.
Спасибо за наводку. Такое чувство, что связано действительно с этим, потому что запрос, содержащий только английские символы, например "kitchen", дает результат.
Использовал следующий код, чтобы определить локаль:
Код
$locale = setlocale('LC_ALL', 0);
echo $locale;
При запуске из браузера в переменной $locale значение "C". При запуске из консоли — "LC_CTYPE=en_US.UTF-8; LC_NUMERIC=C; LC_TIME=C;LC_COLLATE=C; LC_MONETARY=C; LC_MESSAGES=C; LC_PAPER=C; LC_NAME=C; LC_ADDRESS=C; LC_TELEPHONE=C; LC_MEASUREMENT=C; LC_IDENTIFICATION=C"
Я надеялся, что принудительная установка локали в значение "С" решит проблему, но нет. Добавил строчку setlocale('LC_ALL', 'C'); в самое начало скрипта. Русскоязычные поисковые запросы по прежнему не дают результата.
Пробовал еще варианты ru_RU.UTF-8, ru_RU, также безрезультатно.
Сработало, спасибо! Правда в версиях php > 5.3 нет возможности менять параметр mbstring.func_overload через ini_set(), поэтому пришлось ставить ее в настройках сервера. Но это уже вторично.
На всякий случай приведу полную финальную версию скрипта, которая работает:
Код
ini_set('mbstring.func_overload', '2'); // для версий php < 5.3
ini_set('mbstring.internal_encoding', 'UTF-8');
set_time_limit(0);
ignore_user_abort(true);
$_SERVER['DOCUMENT_ROOT'] = '/var/www';
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS',true);
define('BX_CRONTAB', true);
define('BX_NO_ACCELERATOR_RESET', true);
define('SITE_ID', 's1');
define('LANG', 'ru');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
if (!CModule::IncludeModule('search')) {
die('Search module not included');
}
$time_start = time();
$progress = array();
$max_execution_time = 10000; // все элементы индексируются только при большом шаге
while (is_array($progress)) {
$progress = CSearch::ReIndexAll(true, $max_execution_time, $progress);
}
$total_time = time() - $time_start;
echo 'reindex finished. total time: ' . $total_time . ' seconds, indexed elements: ' . $progress . "\r\n";
Евгений Задорин пишет: Сработало, спасибо! Правда в версиях php > 5.3 нет возможности менять параметр mbstring.func_overload через ini_set(), поэтому пришлось ставить ее в настройках сервера. Но это уже вторично.
На всякий случай приведу полную финальную версию скрипта, которая работает:
Код
ini_set('mbstring.func_overload', '2'); // для версий php < 5.3
ini_set('mbstring.internal_encoding', 'UTF-8');
set_time_limit(0);
ignore_user_abort(true);
$_SERVER['DOCUMENT_ROOT'] = '/var/www';
define('NO_KEEP_STATISTIC', true);
define('NOT_CHECK_PERMISSIONS',true);
define('BX_CRONTAB', true);
define('BX_NO_ACCELERATOR_RESET', true);
define('SITE_ID', 's1');
define('LANG', 'ru');
require($_SERVER['DOCUMENT_ROOT'] . '/bitrix/modules/main/include/prolog_before.php');
if (!CModule::IncludeModule('search')) {
die('Search module not included');
}
$time_start = time();
$progress = array();
$max_execution_time = 10000; // все элементы индексируются только при большом шаге
while (is_array($progress)) {
$progress = CSearch::ReIndexAll(true, $max_execution_time, $progress);
}
$total_time = time() - $time_start;
echo 'reindex finished. total time: ' . $total_time . ' seconds, indexed elements: ' . $progress . "\r\n";
Это значит запускать файл search_reindex.php каждые 24 часа, результат записывать в файл search_reindex.log. Абсолютные пути и названия файлов, естественно, прописываете свои.
Это значит запускать файл search_reindex.php каждые 24 часа, результат записывать в файл search_reindex.log. Абсолютные пути и названия файлов, естественно, прописываете свои.