Здесь шпаргалка по обновлению сайтов, работающих под управлением LMS "Moodle".
Прежде всего, так уж получается, что зачастую обновлять приходится сайты, которые работали в своём исходном состоянии годами. Например, совсем недавно модернизировали весьма активно работающую образовательную площадку с версии "3.0" (2015 год) до "3.9" (2020 год). С учётом того, что у площадки при этом накапливаются сотни гигабайт данных, тысячи курсов, неисчислимое множество взаимодействий преподавателей и учащихся, в один клик такое обновлять крайне рискованно. Я предпочитаю предварительно запускать отдельную временную площадку, копию исходной, которую обновляю и отдаю на проверку службе поддержки пользователей, которые тестируют основной востребованный функционал несколько дней, и только с случае полностью гладкой работы мы обновляем уже основной сайт.
Последовательность дальнейших действий:
1. Создание действующей копии обновляемого сайта.
2. Обновление тестового сайта.
3. Обновление действующего сайта.
2. Обновление тестового сайта.
3. Обновление действующего сайта.
Создание действующей копии обновляемого сайта.
Создаём директории тестовой площадки:
# mkdir -p /var/www/upg1-moodle.example.net/www
# mkdir -p /var/www/upg1-moodle.example.net/moodledata
# mkdir -p /var/www/upg1-moodle.example.net/moodledata
Копируем исполняемый код moodle-сайта в тестовой площадку:
# cp -a /var/www/moodle.example.net/www /var/www/upg1-moodle.example.net/www
Копируем файлы данных в выделенный раздел (примонтированное по NFS хранилище, обычно), предназначенный для размещения больших объёмов данных, тестовой площадки:
# cp -a /var/www/moodle.example.net/moodledata /var/www/upg1-moodle.example.net/moodledata
В случае, когда объём файлов данных зашкаливает за сотни Гигабайт, нет смысла копировать их все во временную площадку, предназначенную лишь для прогона процедуры обновления кода сайта - для проверки функциональности вполне достаточно забрать лишь свежие файлы, двухнедельной давности, например таким образом:
# rsync -a /var/www/moodle.example.net/moodledata/ /var/www/upg1-moodle.example.net/moodledata --exclude filedir
# mkdir -p /var/www/upg1-moodle.example.net/moodledata/filedir
# cd /var/www/moodle.example.net/moodledata/filedir
# find ./ -mtime -14 -type f -exec cp --parents "{}" /var/www/upg1-moodle.example.net/moodledata/filedir \;
# mkdir -p /var/www/upg1-moodle.example.net/moodledata/filedir
# cd /var/www/moodle.example.net/moodledata/filedir
# find ./ -mtime -14 -type f -exec cp --parents "{}" /var/www/upg1-moodle.example.net/moodledata/filedir \;
Выгружаем "дамп" БД исходной площадки:
# mysqldump -u root moodle_example_net > /var/www/upg1-moodle.example.net/moodle_example_net.sql
Как вариант, если БД (или некоторые таблицы) исходного moodle-сайта была создана в кодировке "utf8" вместо настоятельно рекомендуемой современной "utf8mb4", во время обновления самое время скорректировать это, выгрузив "дамп" с явным указанием требуемой кодировки:
# mysqldump -u root --complete-insert --extended-insert --default-character-set=utf8mb4 --single-transaction --skip-set-charset --add-drop-database -B moodle_example_net > /var/www/upg1-moodle.example.net/moodle_example_net.sql
# sed -i.bak -e 's/DEFAULT CHARACTER SET utf8_unicode_ci/DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci/' -e 's/DEFAULT CHARSET=utf8_unicode_ci/DEFAULT CHARSET=utf8mb4/' /var/www/upg1-moodle.example.net/moodle_example_net.sql
# sed -i.bak -e 's/DEFAULT CHARACTER SET utf8_unicode_ci/DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci/' -e 's/DEFAULT CHARSET=utf8_unicode_ci/DEFAULT CHARSET=utf8mb4/' /var/www/upg1-moodle.example.net/moodle_example_net.sql
Создаём БД для тестовой площадки:
# mysql
MySQL> DROP DATABASE `upg1_moodle_example_net`;
MySQL> CREATE DATABASE `upg1_moodle_example_net` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MySQL> CREATE USER 'upg1_moodle_example_net'@'localhost' IDENTIFIED BY 'dbPassword';
MySQL> GRANT ALL PRIVILEGES ON `upg1_moodle_example_net`.* TO 'upg1_moodle_example_net'@'localhost';
MySQL> FLUSH PRIVILEGES;
MySQL> QUIT;
MySQL> DROP DATABASE `upg1_moodle_example_net`;
MySQL> CREATE DATABASE `upg1_moodle_example_net` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
MySQL> CREATE USER 'upg1_moodle_example_net'@'localhost' IDENTIFIED BY 'dbPassword';
MySQL> GRANT ALL PRIVILEGES ON `upg1_moodle_example_net`.* TO 'upg1_moodle_example_net'@'localhost';
MySQL> FLUSH PRIVILEGES;
MySQL> QUIT;
Загружаем в БД тестовой площадки "дамп", полученный с исходной:
# mysql -u upg1_moodle_example_net -p upg1_moodle_example_net < /var/www/upg1-moodle_example_net/moodle_example_net.sql
Модифицируем конфигурационный файл тестового moodle-сайта, заменяя там все параметры, имеющие отношение к исходному сайту на те, что воссозданы для тестовой площадки:
# vi /var/www/upg1-moodle.example.net/www/config.php
moodle_example_net -> upg1_moodle_example_net
moodle.example.net -> upg1-moodle.example.net
dbpass -> ...
wwwroot -> ...
dataroot -> ...
moodle.example.net -> upg1-moodle.example.net
dbpass -> ...
wwwroot -> ...
dataroot -> ...
Скорее всего понадобится скорректировать права доступа к файлам тестовой площадки, по везде применяемому мною принципу:
# chown -R www-data:www-data /var/www/upg1-moodle.example.net
# setfacl --recursive --no-mask --modify user::rwX,group::rwX /var/www/upg1-moodle.example.net
# setfacl --recursive --no-mask --modify user:www-data:X /var/www/upg1-moodle.example.net
# setfacl --recursive --no-mask --modify user::rwX,group::rwX /var/www/upg1-moodle.example.net
# setfacl --recursive --no-mask --modify user:www-data:X /var/www/upg1-moodle.example.net
Финальным аккордом копируем исходную конфигурацию сайта для web-сервера, и корректируем её, указывая на тестовую площадку:
# cp /etc/nginx/sites-available/moodle.example.net.conf /etc/nginx/sites-available/upg1-moodle.example.net.conf
# vi /etc/nginx/sites-available/upg1-moodle.example.net.conf
# vi /etc/nginx/sites-available/upg1-moodle.example.net.conf
moodle.example.net -> upg1-moodle.example.net
Активируем новую конфигурацию web-сервера и запускаем в работу, предварительно проверив синтаксис:
# ln -s /etc/nginx/sites-available/upg1-moodle.example.net.conf /etc/nginx/sites-enabled/upg1-moodle.example.net.conf
# nginx -t && nginx -s reload
# nginx -t && nginx -s reload
Проверяем, работает ли тестовый сайт идентично исходному.
Обновление тестового сайта.
Рассмотрим процедуру обновления от "Moodle 3.2.7" до "3.6.10" (выше в один приём нельзя, ибо меняются требования к PHP-интерпретатору).
Прежде всего важно выяснить, какие дополнения к дистрибутивной версии внесены со стороны неопытных разработчиков, влезающих своими кривыми ручками в ядро сайта.
Выясняем точную версию дистрибутива действующего сайта:
# cat /var/www/upg1-moodle.example.net/www/version.php
<?php
....
$release = '3.2.7 (Build: 20180115)';
$branch = '32';
....
....
$release = '3.2.7 (Build: 20180115)';
$branch = '32';
....
Находим и загружаем оригинальный дистрибутив нужной версии:
https://download.moodle.org/stable32/
moodle-3.2.7.tgz 2018-01-13 03:35 38M
https://download.moodle.org/stable32/moodle-3.2.7.tgz
moodle-3.2.7.tgz 2018-01-13 03:35 38M
https://download.moodle.org/stable32/moodle-3.2.7.tgz
# cd /usr/src
# wget https://download.moodle.org/stable32/moodle-3.2.7.tgz
# wget https://download.moodle.org/stable32/moodle-3.2.7.tgz
Распаковываем архив дистрибутива в произвольную директорию и выявляем изменения в коде:
# mkdir -p /var/tmp/moodle327/src
# tar -xvf /usr/src/moodle-3.2.7.tgz -C /var/tmp/moodle327/src --strip-components=1
# diff -qurbB /var/tmp/moodle327/src /var/www/upg1-moodle.example.net/www
# tar -xvf /usr/src/moodle-3.2.7.tgz -C /var/tmp/moodle327/src --strip-components=1
# diff -qurbB /var/tmp/moodle327/src /var/www/upg1-moodle.example.net/www
Все обнаруженные отличия следует в дальнейшем перенести в новую инсталляцию, надеясь, что плагины и темы корректно обновятся, а самописные расширения (по большей части не оформленные по стандартам LMS "Moodle") смогут работать с обновлённым ядром.
Теперь загружаем дистрибутив той версии, до которой нужно или можно обновляться:
# cd /usr/src && wget https://download.moodle.org/download.php/direct/stable36/moodle-3.6.10.tgz
Заменяем ядро сайта новым, с сохранением конфигурации:
# mv /var/www/upg1-moodle.example.net/www /var/www/upg1-moodle.example.net/www-327
# mkdir -p /var/www/upg1-moodle.example.net/www
# tar -xvf /usr/src/moodle-3.6.10.tgz -C /var/www/upg1-moodle.example.net/www --strip-components=1
# cp /var/www/upg1-moodle.example.net/www-327/config.php /var/www/upg1-moodle.example.net/www/config.php
# mkdir -p /var/www/upg1-moodle.example.net/www
# tar -xvf /usr/src/moodle-3.6.10.tgz -C /var/www/upg1-moodle.example.net/www --strip-components=1
# cp /var/www/upg1-moodle.example.net/www-327/config.php /var/www/upg1-moodle.example.net/www/config.php
Копируем те отличия от кода исходного дистрибутива, что ранее обнаружили посредством "diff", в структуру нового ядра сайта.
Устанавливаем необходимые права доступа к файлам обновлённого ядра тестовой площадки:
# chown -R www-data:www-data /var/www/upg1-moodle.example.net/www
# setfacl --recursive --no-mask --modify user::rwX,group::rwX /var/www/upg1-moodle.example.net/www
# setfacl --recursive --no-mask --modify user:www-data:X /var/www/upg1-moodle.example.net/www
# setfacl --recursive --no-mask --modify user::rwX,group::rwX /var/www/upg1-moodle.example.net/www
# setfacl --recursive --no-mask --modify user:www-data:X /var/www/upg1-moodle.example.net/www
Переходим в административную часть web-интерфейса сайта (/admin/index.php) и запускаем процедуру обновления "базы данных" сайта, а потом и плагинов (/admin/plugins.php):
Обновление действующего сайта.
Очевидно, что при обновлении действующего сайта пропускаются процедуры создания тестового стенда и выявления отличий в коде ядра.
Перед процедурой обновления сайт нужно обязательно перевести в режим обслуживания (admin/settings.php?section=maintenancemode), чтобы в этот период не пускать в него пользователей. Также можно закрыть доступ к сайту посредством web-сервера, оставив проход только себе.
В качестве небольшой оптимизации перед копированием файлов сайта желательно зачистить "кеши":
# sudo -u www-data php /var/www/moodle.example.net/www/admin/cli/purge_caches.php