Сначала копия, потом прод: как обновлять CMS и не потерять платежи и формы
Я обновляю CMS через копию сайта: сначала проверяю совместимость ядра, темы и расширений, затем прохожу важные для бизнеса сценарии. Перед релизом сохраняю файлы и базу, а заранее записанные условия отката помогают быстро вернуть рабочую версию, если заказ или форма сломались.
Почему нельзя жать «Обновить» на рабочем сайте
В прошлой статье серии мы разобрали, что делать с заброшенным плагином: заменить, удалить или принять риск. Следующий вопрос — как обновлять оставшиеся компоненты магазина. Обновления закрывают часть известных уязвимостей; это один из пунктов защиты сайта, но кнопка «Обновить всё» не знает, что тема правлена вручную, а модуль оплаты зависит от старого интерфейса ядра.
Что ломается на практике чаще всего: оформление (тема переопределяет шаблоны, которые изменились), оплата (модуль платёжного шлюза не совместим с новой версией магазина), формы обратной связи (плагин форм, капча, отправка почты), интеграция с учётной системой и доставкой. Хуже всего то, что половина этих поломок не видна на главной странице. Сайт открывается, админ доволен, а заказы перестали падать в 1С, и узнаёте вы об этом от бухгалтерии через три дня. Платёжный модуль может молча отдавать ошибку только при определённом способе оплаты, а форма — терять письма только с вложением.
Поэтому я считаю обновление релизом, а не кликом. У релиза есть тестовая копия, перечень сценариев, полный бэкап, окно работ и условия возврата. В карточке фиксирую версии CMS, PHP, базы данных и расширений: если после обновления что-то пошло не так, можно восстановить исходную связку, а не гадать, что стояло раньше. Это ещё и снимает зависимость от памяти одного администратора. Бумажная работа? Минуты. Поиск потерянной версии в аварии — совсем другой жанр.
Из базы знаний: перед обновлением CMS нужны полная резервная копия файлов и базы, а список версий CMS, PHP, базы и плагинов стоит сохранить вместе с планом работ. Я проверяю эти пункты до начала обновления.
Как поднять staging-копию и не устроить второй прод
Staging — копия файлов и базы, на которой можно проверить обновления до выхода на рабочий сайт. Я стараюсь повторить версии CMS, PHP, базы и ключевых расширений: если окружение расходится, результат проверки применим лишь частично. Копию размещаю отдельно, закрываю паролем на уровне веб-сервера и запрещаю индексацию. Один запрет в robots.txt не закрывает доступ к содержимому; пароль нужен именно для доступа, а запрет индексации — дополнительная мера.
Самое опасное в staging — то, что копия умеет то же, что и прод. Она может отправить письма клиентам, списать деньги через боевой ключ платёжного шлюза, выгрузить тестовый заказ в 1С и отправить заявку в службу доставки. Поэтому сразу после развёртывания: платёжный модуль переводим в тестовый режим или ставим тестовые ключи, исходящую почту перехватываем или отключаем, интеграции с учётом и доставкой выключаем либо направляем на тестовые контуры. Меня до сих пор веселит, сколько магазинов получали «заказ» от собственного тестового сайта.
Для WordPress переношу файлы и базу, затем меняю адрес через WP-CLI. Сначала экспортируйте базу production командой wp db export prod.sql, затем перенесите дамп и файлы на staging и проверьте, что wp-config.php указывает на отдельную тестовую базу. Команду wp db import prod.sql запускайте только в каталоге этой копии. В примере ниже команда замены сначала работает в режиме dry-run: покажет план замен, не записывая их. Параметр --skip-columns=guid исключает колонку GUID из замены — документация WordPress отдельно предупреждает не менять её содержимое. Для Битрикс и OpenCart также нужны копии файлов и базы, корректные настройки адреса и подключения к базе. После переноса проверяю ссылки и формы: часть адресов может храниться в базе, часть — в конфигурации или коде. На копии WordPress DISABLE_WP_CRON в wp-config.php отключает запуск WP-Cron при загрузке страниц; отдельно проверьте системные задания и интеграции, чтобы они не обращались к боевым сервисам.
- ```bash wp db export prod.sql wp db import prod.sql wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid --dry-run wp search-replace 'https://example.com' 'https://staging.example.com' --skip-columns=guid ```
- Платёжный модуль — тестовый режим
- Исходящая почта — отключена или перехвачена
- Интеграции с 1С и доставкой — выключены
- Доступ — по паролю, индексация запрещена
Что проверять на копии после обновления
До обновления записываю исходные версии ядра, PHP, базы, плагинов и темы, а также состояние расширений. Для WordPress использую wp core version, wp plugin list и wp theme list; в других CMS сохраняю список из админки или штатной консоли. Файл кладу рядом с описанием резервной копии. Это конкретный факт из экспертной базы: инвентаризация версий нужна не для отчёта, а чтобы понимать, что именно проверяли и к какой конфигурации возвращаться. На staging обновляю компоненты по одному этапу и отмечаю, менялась ли схема базы. Перед обновлением сверяю заявленную совместимость расширения с целевой версией: в данных WordPress-плагина могут быть поля Tested up to и Requires PHP. Это фильтр для отбора, а не гарантия, что локальные правки и все интеграции переживут релиз; поэтому следом прогоняю сценарии на копии.
Проверка — не «главная открылась». Я прохожу сценарии, на которых зарабатывает бизнес: поиск и фильтр каталога, карточка товара, корзина, оформление заказа с тестовой оплатой, письмо покупателю, появление заказа в админке, форма обратной связи и её доставка, личный кабинет. Потом сравниваю журналы PHP и консоль браузера с исходным состоянием. Предупреждение само по себе не доказывает, что следующий релиз упадёт, но новые ошибки требуют разбора до выхода. Проверяю и с телефона, включая отправку формы и завершение заказа.
Отдельно смотрю на расширения без обновлений и с правками в коде. Если тема или модуль менялись вручную, обновление может перезаписать эти изменения, поэтому сначала сравниваю файлы с исходной версией и фиксирую нужные доработки. У заброшенного расширения проверяю не только дату последнего релиза, но и то, можно ли безопасно заменить его. Например, проблемы с поддержкой плагина и последствия обновления мы разбирали в материале об уязвимости WPForms. Решение о замене принимаю до окна, а не посреди релиза.
- Каталог, поиск, фильтры
- Корзина и заказ с тестовой оплатой
- Письма покупателю и менеджеру
- Формы обратной связи и капча
- Обмен с 1С и доставкой (на тестовом контуре)
- Журнал ошибок PHP до и после
Бэкап перед релизом: что именно сохранить
Перед обновлением прода нужен свежий бэкап. Между ночной копией и релизом приходят новые заказы, и восстановление вчерашней базы их не вернёт. Сохраняю базу, все файлы сайта, включая загрузки и конфигурацию, и перечень версий. Таково базовое правило резервирования из экспертной базы: копия перед изменениями должна охватывать и файлы, и данные. Для MySQL с таблицами InnoDB использую mysqldump --single-transaction: документация MySQL описывает согласованный снимок без блокировки приложений для транзакционных таблиц. MyISAM и MEMORY этим ключом не защищаются от изменений так же, поэтому сначала проверяю движки таблиц. Параметр --routines добавляет хранимые процедуры и функции; для него нужны соответствующие права учётной записи. Копию храню отдельно от диска сайта.
Главное — бэкап должен восстанавливаться. Я разворачиваю архив на тестовой среде и проверяю вход в админку, открытие ключевых страниц и работу заказа. Экспертная база отдельно подчёркивает проверку восстановления: наличие файла архива ещё не доказывает, что из него получится рабочий сайт. Бэкап делают все, проверяет его почти никто. Про копии от хостинга я писал в статье «бэкап сайта и миф хостинга». Замеряю время восстановления именно на своём окружении — универсального срока для любого магазина нет.
Отдельно решаю, что делать с новыми данными во время окна. Если после релиза уже прошёл заказ, восстановление старой базы может его потерять. До начала выбираю один путь: включить режим обслуживания, временно закрыть оформление или подготовить ручную сверку заказов, созданных во время работ. В WordPress режим можно включить командой wp maintenance-mode activate, если WP-CLI доступен и настроен. Проверяю также формы, интеграции и фоновые задания: режим обслуживания не отключает автоматически все внешние системы. Для покупателя лучше ясное сообщение о работах, чем оформление, которое выглядит успешным, но не дошло до магазина.
- ```bash mysqldump --single-transaction --routines -u USER -p DBNAME > before_update.sql tar -czf before_update_files.tar.gz /var/www/example.com ```
Окно релиза и критерии отката
Окно релиза выбираю по нагрузке и доступности людей, которые принимают решение и выполняют откат. Для магазина это часто утро до пика продаж, но ориентир задаёт статистика конкретного сайта. Закладываю время на обновление, повторную проверку ключевых сценариев и наблюдение за заказами и журналами. Не обещаю одинаковую длительность для всех: размер базы, скорость восстановления и число интеграций меняют график. В карточке записываю ответственных и контакты на время работ. Если обе роли у одного человека, он должен быть на связи и иметь доступ к проверенному архиву.
Критерии отката записываются до релиза, иначе в момент проблемы начинается «давайте ещё посмотрим». Мой список: заказ не проходит; форма или письмо не доходят; ключевая страница отдаёт ошибку 500 или пустой экран; заказы перестали попадать в учётную систему; скорость заметно ухудшилась относительно замеров до обновления. Любой пункт — повод остановить релиз и свериться с заранее согласованным планом. Для производительности фиксирую базовые показатели до работ и сравниваю одинаковые страницы при сопоставимой нагрузке. Не называю произвольный процент порогом для всех проектов.
Откат — это восстановление файлов и базы из копии перед окном, затем повторная проверка тех же сценариев. Поштучно возвращать плагины рискованно: обновление могло изменить структуру данных, и старая версия расширения может с ней не работать. Поэтому способ восстановления выбираю заранее и проверяю на staging; время зависит от конкретного хранилища, размера сайта и доступа к резервной копии. После возврата фиксирую причину, воспроизвожу её на тестовой копии и назначаю новое окно только после повторного прогона сценариев.
- Тестовый заказ не проходит — откат
- Формы или письма не уходят — откат
- 500 или белый экран на ключевых страницах — откат
- Заказы не попадают в 1С — откат
- Сильный рост времени ответа — откат
Разбор: магазин тканей «Мерка длины», 18 рабочих мест
Для разбора возьму условный магазин тканей «Мерка длины»: 18 рабочих мест, WordPress с WooCommerce, около 30 активных плагинов, тема с правками прошлого подрядчика, обмен заказами с 1С и онлайн-оплата. Обновления делали нерегулярно; после предыдущего корзина не работала два дня. В каталоге около четырёх тысяч позиций с вариантами ширины и состава ткани, поэтому проверять нужно фильтры, корзину и оплату, а не только главную страницу. Это пример рабочего плана, а не обещание, что похожий магазин обновится за тот же срок.
На копии проверка выявила три несовместимости. Старая версия модуля оплаты создавала заказ, но не открывала страницу платёжного шлюза; после проверки совместимой версии модуль обновили. Правки шаблона карточки товара перезаписывались обновлением темы, поэтому мы перенесли их в дочернюю тему. Плагин формы давно не получал обновлений, и его заменили после проверки доставки заявок. Ирония короткая: «не трогали» не значит «не сломается».
Релиз запланировали до открытия магазина. Перед ним сделали свежую копию файлов и базы, включили режим обслуживания, обновили сайт и проверили оплату, формы и обмен с 1С. Затем вернули сайт в рабочий режим и наблюдали за заказами и журналами. Откат не понадобился; критерии и последовательность восстановления были записаны заранее. Дальше команда использует ту же карточку релиза: список расширений, сценарии проверки, подтверждённое восстановление, критерии отката и контакты на время окна. Частоту обновлений определяют по выходу исправлений и риску компонентов, а не по календарному ритуалу.
Частые вопросы
Что такое staging-копия сайта?
Полная копия файлов и базы на том же окружении, закрытая паролем и от индексации, где обновления проверяют до рабочего сайта.
Можно ли обновлять плагины прямо на рабочем сайте?
На простом сайте-визитке риск ниже. На магазине с оплатой и интеграциями — только после проверки на копии и со свежим бэкапом.
Как не отправить письма и платежи с копии сайта?
Сразу после развёртывания переведите платёжный модуль в тестовый режим, отключите исходящую почту и интеграции с 1С и доставкой.
Когда принимать решение об откате?
По заранее записанным критериям: не проходит заказ, не уходят формы и письма, ошибки 500, заказы не попадают в учёт.
Почему нельзя откатить один плагин?
Обновление может изменить схему данных в базе. Старая версия на новой схеме ведёт себя непредсказуемо, надёжнее полный откат.
Источники
- WP-CLI: wp search-replace — Подтверждение параметров --dry-run и --skip-columns, включая пример с GUID: https://developer.wordpress.org/cli/commands/search-replace/
- WordPress: команды и требования расширений — Официальный список команд WP-CLI для ядра и плагинов; документация формата плагина описывает поля Tested up to и Requires PHP: https://developer.wordpress.org/cli/commands/ и https://developer.wordpress.org/plugins/wordpress-org/how-your-readme-txt-works/
- WordPress: обновление и резервные копии — Резервная копия сайта перед обновлением и риски отката файлов и базы: https://developer.wordpress.org/advanced-administration/upgrade/upgrading/
- MySQL: mysqldump — Поведение --single-transaction для InnoDB и ограничения для нетранзакционных таблиц: https://dev.mysql.com/doc/refman/8.0/en/mysqldump.html
- WordPress: автообновления плагинов и тем — Настройка автообновлений по отдельным плагинам и темам и рекомендации по бэкапу: https://wordpress.org/documentation/article/plugins-themes-auto-updates/
- WordPress: настройка wp-config.php — Поведение константы DISABLE_WP_CRON: https://developer.wordpress.org/advanced-administration/wordpress/wp-config/



