Перейти к содержимому

Обновление платформы изнутри - лицензия, шаги, файлы и база

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

Механика

Система обновлений продукта носит имя SiteUpdate и обновляет ровно три вещи: ядро, модули и языковые файлы платформы. Всё перечисленное лежит внутри каталога /bitrix/, и обновление считает этот каталог своей единоличной собственностью. Каталог /local/, шаблоны сайта и загруженные посетителями файлы система не трогает вообще.

Единицей обновления служит не продукт целиком, а отдельный модуль со своей собственной версией. Версия каждого модуля лежит на диске, в файле install/version.php его каталога, а вовсе не в базе. Система сравнивает версии установленных модулей с версиями на сервере обновлений и собирает из полученной разницы список доступных пакетов.

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

Право на загрузку проверяет сервер обновлений, а не сам сайт. Лицензионный ключ лежит отдельным файлом ядра /bitrix/license_key.php, копия продукта регистрируется на сервере обновлений, а срок продления определяет, что этот сервер готов отдать. Пробный ключ обновлений не получает совсем, и демонстрационную копию обновляют только установкой свежего дистрибутива.

Архивы обновлений забирает сам сервер сайта, а не браузер администратора. Клиенту обновлений нужны расширения XML и DOM для разбора ответа плюс работающие сокет-функции для исходящего соединения. Закрытый наружу порт даёт сообщение «Connection timed out» с кодом 110 вместо внятного объяснения причины.

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

На диске меняется содержимое каталога модуля и его копии в общедоступных папках платформы: скрипты админки, клиентские расширения и системные компоненты. Любая правка внутри /bitrix/ затирается молча, без предупреждения и без следа в журнале обновлений.

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

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

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

Шаги

  1. Снять версии установленных модулей прямо с диска и увидеть, насколько ядро разошлось с остальными модулями.
  2. Проверить ключ, срок продления и исходящий доступ с самого сервера сайта, а не из браузера администратора.
  3. Снять копию файлов и базы одним моментом времени, потому что штатного отката у системы обновлений нет.
  4. Запустить обновление и дождаться конца всех шагов, не закрывая страницу и не перезагружая её вручную.
  5. Сбросить кэш, выполнить отложенный SQL из сообщения админки и прочитать журнал ошибок за время обновления.

Код

Смотрим версии модулей на диске:

Окно терминала
for f in bitrix/modules/*/install/version.php; do
module=$(basename "$(dirname "$(dirname "$f")")")
# версия лежит в файле модуля, в массиве $arModuleVersion, а не в базе
printf '%-22s %s\n' "$module" "$(grep -oE "VERSION.{0,20}" "$f" | head -1)"
done
# тот же файл читает класс-установщик модуля при выводе списка обновлений
ls -d local/modules/*/install/version.php 2>/dev/null # свои модули считаются отдельно

Ровно эти строки система сравнивает с версиями на сервере обновлений. Версия главного модуля показывает, насколько давно сайт обновлялся, а её расхождение с остальными подсказывает, где прошлое обновление оборвалось.

Проверяем ключ и регистрацию копии:

$key = $_SERVER['DOCUMENT_ROOT'] . '/bitrix/license_key.php';
echo file_exists($key) ? "файл ключа на месте\n" : "файла ключа нет\n";
echo \Bitrix\Main\Config\Option::get('main', 'update_site_key'), "\n";
echo \Bitrix\Main\Config\Option::get('main', '~PARAM_MAX_SITES'), "\n";
// ключ хранится отдельным файлом ядра, а не в настройках модуля и не в базе
// параметры лицензии приезжают с сервера обновлений и кладутся в опции модуля
// срок продления проверяется на стороне сервера обновлений, а не на сайте

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

Проверяем, чем клиент ходит наружу:

Окно терминала
php -r 'var_dump(extension_loaded("dom"), extension_loaded("xml"), function_exists("fsockopen"));'
php -r '$s = @fsockopen("www.1c-bitrix.ru", 443, $e, $m, 5); var_dump((bool) $s, $m);'
php -r 'var_dump(ini_get("mbstring.func_overload"));' # ненулевое значение блокирует обновление
# разбор ответа держится на XML и DOM, соединение - на сокет-функциях
# код ошибки 110 в сообщении означает таймаут исходящего соединения

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

Смотрим, что обновление заменило на диске:

Окно терминала
find bitrix/modules -maxdepth 1 -type d -newermt '-1 day' # обновлённые модули
find local -type f -newermt '-1 day' | head # здесь пусто всегда
ls -d bitrix/admin bitrix/js bitrix/components/bitrix # копии файлов модулей
ls -d bitrix/templates/.default local/templates 2>/dev/null # системные шаблоны тоже в /bitrix/
# шаблоны сайта живут в /local/templates/ и обновлением не заменяются

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

Смотрим правку базы, отданную администратору:

-- платформа выводит такой запрос в шапке админки и просит выполнить его руками
create index ix_iblock_element_prop_val
on b_iblock_element_property(VALUE(50), IBLOCK_PROPERTY_ID, IBLOCK_ELEMENT_ID);
-- проверить, выполнен ли он уже, можно списком индексов той же таблицы
show index from b_iblock_element_property;
-- запрос выполняют в разделе «Настройки - Инструменты - SQL запрос»

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

Снимаем копию перед первым шагом:

Окно терминала
# штатный бэкап из консоли: результат ложится в /bitrix/backup/
sudo -u bitrix php -f /home/bitrix/www/bitrix/modules/main/tools/backup.php do_update
df -h /home/bitrix # места нужно и под копию, и под распаковку обновлений
# разворачивают копию скриптом restore.php, положенным в корень сайта
# файлы и база должны быть сняты одним моментом времени, иначе откат несогласован

Откат у системы обновлений отсутствует как понятие. Копия файлов без базы того же момента вернёт старое ядро к уже изменённой структуре таблиц, и сайт после такого возврата не поднимется.

Приводим кэш в согласие с файлами:

Окно терминала
grep -rn 'opcache.validate_timestamps' /etc/php.d/ 2>/dev/null
sudo systemctl restart php-fpm # сброс кэша опкода после окончания обновления
# значение 0 отдаёт старые файлы уже после их замены на диске
# на время обновления параметр переключают в On, потом возвращают обратно
# управляемый кеш чистят из админки, а не удалением /bitrix/managed_cache/ руками

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

Отличаем обновление продукта от обновления окружения:

Окно терминала
/root/menu.sh # окружение: пакеты сервера, nginx, база, версии PHP
# пункт «2. Manage localhost» - «6. Update server» обновляет саму машину
# продукт обновляется из админки и меняет только каталог /bitrix/
# PHP и база при обновлении окружения не переключаются сами: это отдельный пункт меню
# кастомные конфиги переживают обновление только в файлах вида z_bx_custom.*

Две операции легко перепутать по названию, но одна не заменяет другую. Свежее окружение не обновляет продукт, а свежий продукт не переносит сайт на новую ветку интерпретатора.

Ограничения

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

Ручная правка файлов ядра или структуры таблиц делает автообновление непредсказуемым. Скрипт очередного шага рассчитывает на известное ему состояние модуля и падает на первом же расхождении с ожидаемым.

Параметр mbstring.func_overload блокирует и установку продукта, и его обновление. Он устарел ещё в PHP 7.2 и не поддерживается платформой начиная с версии главного модуля 20.100.0, поэтому его обнуляют до запуска обновления.

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

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

Типичные проблемы

Кнопка установки обновлений не нажимается.

Проверка системы показывает расхождение времени между базой и веб-сервером на целый час. Система обновлений сверяет отметки времени и отказывается работать при таком расхождении.

Обновление падает на попытке удалить индекс таблицы.

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

Обновление заканчивается сообщением о блокировке сессии.

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

Страница обновлений отдаёт ошибку о ненайденном классе.

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

После обновления падает копия модуля ядра из каталога local.

Обновление заменило модуль в каталоге платформы, а его копию в пользовательском каталоге не тронуло. Копия подключается вместо оригинала и зовёт классы, которых в её версии ещё нет.

Сайт после обновления работает заметно медленнее прежнего.

Платформа отдала тяжёлую правку базы администратору сообщением в шапке админки. Пока запрос не выполнен, инфоблоки продолжают работать по старому набору индексов.

Частые вопросы

Что именно обновляет система обновлений?

Ядро, модули и языковые файлы продукта внутри каталога /bitrix/. Каталог /local/, шаблоны сайта и загруженные файлы она не трогает совсем.

Можно ли обновлять пробную версию штатными методами?

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

Почему обновление обрывается на середине?

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

Можно ли откатить обновление продукта?

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

Обновление битрикса и обновление окружения - это одно и то же?

Нет. Продукт обновляется из админки и меняет каталог /bitrix/, а окружение обновляется из консольного меню и меняет пакеты самого сервера.

Смежное

Первоисточник