Автогенерация карты сайта sitemap.xml с помощью crontab

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

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

Почему это очень нужно именно на больших магазинах? Да дело в том, что обновление всех файлов карты сайта повешаны на события изменения/добавления/удаления элемента и раздела инфоблока, что при синхронизации каталога товаров, когда например, обновляется товар или создается новый, при каждой такой операции и обновляется соответствующий файл карты сайта, например в корне сайта это файл sitemap_iblock_6.xml, при 100 000 товарах он может быть размером в несколько мегабайт, кто уже давно в веб-разработке думаю понимает, какая это нагрузка на дисковую систему и память, когда многомегабайтный файл на диске целый час не переставая перезаписывается, в память пишется вся карта, потом эта карта сбрасывается на диск, и так например каждый час 100 000 товаров синхронизируются создавая просто огроменную нагрузку на сервер, дешевая VPS-ка такой нагрузки уже не выдержит, думаю многие с этим уже сталкивались, а кому-то и предстоит столкнуться.

Еще конечно события генерации карты сайта и на другие модули повешаны, но в этой статье мы их не касаемся, нам нужны только инфоблоки, синхронизация к примеру 100 000 товаров с характеристиками, всякие форумы, реклама и т.д. мне не нужны, а вы смотрите сами, какие у вас стоят задачи.

Как я узнал про это? Да как-то все настраивал у одного клиента, как положено, настроил карту сайта, включил на запуск и тут все сначала стало тормозить, потом рухнул сервер, после перезагрузки он тоже не мог долго работать.

Что делать? К сожалению синхронизация на сайте написана так, что там при каждом обновлении товара сотни запросов делаются к базе, никакой сверки данных нет, просто все перезаписывается, в циклах дергаются и настройки нескольких модулей из базы, все это переплетается как паутина в десятках файлов и нескольких модулях, часть стандартных, часть самописных, да еще и диски не сервере отстой.
Вообще проще, надежнее и выгоднее переписать модуль с нуля со всеми оптимизациями, чем переписывать текущий, поверьте, встречал такие модули и интернет-магазины, их даже выгодней сделать с нуля заново, чем тратить сотни тысяч рублей на ежегодное сопровождение и хоть какое-то улучшение ситуации, что очень затратно в разы и обременяет всех на свете, и менеджеров магазина, и покупателей, клиент конечно никому и ни во что уже не верит, на это не идет, а зря, профессионалов надо слушать.

Раз ситуация безвыходная, пусть все остается как есть и синхронизируется дальше, а чтобы карта сайта создавалась с минимальной нагрузкой на сервер один раз в час по крону,  я поступил таким образом:

1) Отключаем пересоздание карты сайта в инфоблоках
Это готовый файл, можете открыть один раз, увидите надпись "OK", значит все готово, обработчики удалились из базы, тут кстати обработчики и для форумов есть, они тоже будут участвовать в файле для крона, почему, это я уже не помню.
Найти весь список событий можете в этом файле /bitrix/modules/seo/install/index.php::UnInstallDB()
<?php
use \Bitrix\Main\Application;
require_once($_SERVER["DOCUMENT_ROOT"] . "/bitrix/modules/main/include/prolog_before.php");

global $APPLICATION;

$POST_RIGHT = $APPLICATION->GetGroupRight("main");
if ($POST_RIGHT < "W")
    $APPLICATION->AuthForm("Доступ запрещен");

$eventManager = \Bitrix\Main\EventManager::getInstance();

$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockSectionAdd", "seo", "\\Bitrix\\Seo\\SitemapIblock", "addSection");
$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockElementAdd", "seo", "\\Bitrix\\Seo\\SitemapIblock", "addElement");

$eventManager->unRegisterEventHandler("iblock", "OnBeforeIBlockSectionDelete", "seo", "\\Bitrix\\Seo\\SitemapIblock", "beforeDeleteSection");
$eventManager->unRegisterEventHandler("iblock", "OnBeforeIBlockElementDelete", "seo", "\\Bitrix\\Seo\\SitemapIblock", "beforeDeleteElement");
$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockSectionDelete", "seo", "\\Bitrix\\Seo\\SitemapIblock", "deleteSection");
$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockElementDelete", "seo", "\\Bitrix\\Seo\\SitemapIblock", "deleteElement");

$eventManager->unRegisterEventHandler("iblock", "OnBeforeIBlockSectionUpdate", "seo", "\\Bitrix\\Seo\\SitemapIblock", "beforeUpdateSection");
$eventManager->unRegisterEventHandler("iblock", "OnBeforeIBlockElementUpdate", "seo", "\\Bitrix\\Seo\\SitemapIblock", "beforeUpdateElement");
$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockSectionUpdate", "seo", "\\Bitrix\\Seo\\SitemapIblock", "updateSection");
$eventManager->unRegisterEventHandler("iblock", "OnAfterIBlockElementUpdate", "seo", "\\Bitrix\\Seo\\SitemapIblock", "updateElement");

$eventManager->unRegisterEventHandler("forum", "onAfterTopicAdd", "seo", "\\Bitrix\\Seo\\SitemapForum", "addTopic");
$eventManager->unRegisterEventHandler("forum", "onAfterTopicUpdate", "seo", "\\Bitrix\\Seo\\SitemapForum", "updateTopic");
$eventManager->unRegisterEventHandler("forum", "onAfterTopicDelete", "seo", "\\Bitrix\\Seo\\SitemapForum", "deleteTopic");

echo 'OK';

2) Создаем и полностью настраиваем в админке карту сайта
Здесь также будет изменяться время создания карты, в моем случае каждый час.
Вообще все тоже самое будет по крону происходить, как будто вы нажали зеленую кнопку  "Запустить".
В дальнейшем нам пригодится ID карты.
Пример карты моего сайта

3) Скачиваем прикрепленный в статье скрипт
seo_sitemap_run.php и копируем в папку /bitrix/php_interface/crontab

В архиве готовая структура, можете прям скопировать папку, не думаю что у вас такой же файл окажется.
А также в архиве есть файл .htaccess, он будет полезен для защиты скрипта от внешнего доступа.

4) Добавляем крону на сервере задачу для запуска данного скрипта
/bitrix/php_interface/crontab/seo_sitemap_run.php

Вы можете добавить задачу как вам удобно, хоть через панель сервера/хостера, хоть через консоль PuTTY, а мне удобно и вам советую через стандартный /bitrix/crontab/crontab.cfg в Битриксе.

Почитать о конфигурационном файле crontab.cfg в Битрикс можно прямо в админке на странице Настройка экспорта
Настройки экспорта Битрикс

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

Очень неудобно, когда cron-задачи добавляются где-то в панели сервера/хостера, если там нет никакого экспорта/импорта, а их там может быть несколько десятков, а то и сотен, то надо будет либо вручную все добавлять, либо какой-то свой файл с кронами кормить на самом сервере, а если вы перенесли сайт и вообще забыли про эти кроны, вспомнили только через неделю, а исходный сервер уже удален и данные не сохранились, никакая документация по сайту разработчиками не велась, ситуация может быть печальная, а так вы вместе с сайтом перенесете все задачи для крона, как вспомните, то одним движением руки очень красиво их все запустите и смело отчитаетесь начальству об успешном решении проблемы после переезда.

Как видно из документации, все не так сложно:

а) Создаете этот файл сами или настраиваете какой-то экспорт тогда Битрикс его создаст
б) Добавляете в этот файл команды/задачи для крона, каждая команда с новой строки и в конце одна пустая строка обязательна.
в) Для установки конфигурационного файла необходимо соединиться с вашим сайтом по SSH (SSH2) или какому-либо другому аналогичному протоколу, запустить консоль PuTTY.
В консоли нужно просто выполнить такую команду, вставить по правому Shift + Insert и нажать Enter
crontab /home/tuning-soft.ru/html/bitrix/crontab/crontab.cfg

Для просмотра списка установленных задач можно выполнить команду
crontab -l

Для удаления списка установленных задач можно выполнить команду
crontab -r

Абсолютные или относительные пути до скриптов и конфигурационного файла конечно у вас будут свои, мои не надо у себя вводить.

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

У меня команда на каждый час выглядит вот так:
@hourly /usr/bin/php -f ~/web/tuning-soft.ru/html/bitrix/php_interface/crontab/seo_sitemap_run.php action=sitemap_run ID=1 lang=ru

Обратите тут внимание на параметры (экшн, ID-карты, язык) action, ID, lang, так от крона срипту передаются параметры/аргументы в переменной $argv

Обязательно запускайте скрипт с параметрами, ID-карты сайта указывайте тот, что видите у себя в админке, иначе не будет работать.

В прикрепленном к статье скрипте все сделано, там вам скорее всего ничего не нужно будет изменять, на 16 версии Битрикс у меня пока все работает, сам скрипт взят у Битрикса, который дергается аяксом по зеленой кнопке "Запустить", только переделан под cron.

Сейчас уже многое  я вижу по обновлениям добавилось, но все еще работает, так что, все равно за картой сайта иногда наблюдайте, если обновляете Битрикс, у меня вот такая карта, видно как каждый час она обновляется

Карта сайта Битрикс

Вообще можете хоть каждые 5 минут ее генерить, все зависит от размера вашего сайта и его нагруженности, например, у клиента с 60 000 товарами такая карта пересоздается за 1-2 минуты, согласитесь, как это быстро и с минимальной нагрузкой, хотя это еще тормозной реговский ssd-диск на их новых тарифах, на крутом и реально быстром SSD будет вообще за секунды создаваться.

На этом все, как крон начнет выполнять задачу, карта начнет обновляться каждый час.
Кстати, в админке вы также можете обновлять карту вручную, данный скрипт запускается отдельно и на админку никак не влияет, он только берет настройки из указанной в параметрах карты и запускается кроном в заданное время.
При необходимости удаленные события можете вернуть, надо только заменить unRegisterEventHandler() на registerEventHandler() и один раз запустить скрипт.

Рекомендации

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

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

У некоторых клиентов недоумение, как ssd-диск может быть медленным, да, они тоже разные, как и старые hdd-диски, есть быстрые, а есть медленные, все ssd быстрые  по отношению к hdd, а между собой они также конкурируют по скорости и надежности.
У меня было два самых быстрых тогда SSD OCZ Vector, скорость нереальная, очень быстрые диски, но радость моя была недолгой, брал я их тогда еще до кризиса за 7К и оба навернулись, первого хватило всего на 2 месяца, второго на 6 месяцев, с первым я чуть не попал, сверстал два интернет-магазина шин и дисков и аккумуляторный, в пятницу я их залил на сервер показывать клиентам, в воскресенье диск умер и не подлежал восстановлению даже в сервисе.

Сейчас я второй год пользуюсь надежным SSD Plextor PX-128M5Pro и HDD WDC WD1003FZEX-00MK2A0 1000GB и на глаз разницы между ними я не вижу, просто SSD быстрее думает и откликается на команды, HDD пока подумает и откликнется пройдут секунды, по замерам да, быстрее, но внешне не заметно, как два одинаковых диска, вообще все диски я брал только Western Digital, они просто вечные, даже раптор у меня был, трещал спустя два года невыносимо, но работал, не было такого, вот так умер и все.

Сейчас просто маркетингом также промывают мозги по поводу SSD-дисков, мол они все супер-быстрые, а вот и нет, заливаете сайт и не понимаете, почему совсем чуть-чуть стало лучше, а заявлено скорость x200 )))
Также как у Битрикс композитом вам всем промывают мозг со скоростью x100, понимаете, уже должно быть x300, а чета все равно все тормозит, а вот и php7 нагрянул со скоростью x2, наверно уже должна быть скорость x600, о, а вот еще php-fpm и nginx, итого загрузка сайта должна уже быть 0сек, или даже -10сек, была реально 20сек, а стала например 16сек, и только на втором хите она достигла 12сек, а еще там есть Битрикс CDN и все такое...

Понимаете, так каждый год все какие-то ускорения, а на деле все туфта, выключаете Битрикс CDN и сайт начинает открываться в разы быстрее, да как так-то)))

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

Имя *
Логин (мин. 3 символа)
E-mail *
*— обязательные для заполнения поля
Логин или e-mail
TUNING-SOFT.RU Разработка умных веб-сервисов