Migrate a phpBB3 forum to Discourse

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

Похоже, мне придётся работать с xml_to_markdown.rb?

2 лайка

Моя попытка выполнить тестовый импорт с форума phpBB 3.3.x оказалась провальной, но об этом позже.

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

Если вам нужно отредактировать /script/import_scripts/phpbb3/database/database.rb, чтобы обойти проверку версии, или /script/import_scripts/phpbb3/support/bbcode/xml_to_markdown.rb, чтобы добавить пользовательские BB-коды, делать это следует после входа в режим импорта с помощью команды:

/var/discourse/launcher enter import

После этого вы можете использовать nano для редактирования файлов.

Поскольку моя попытка запустить импорт на форуме phpBB 3.3 не удалась, я не могу быть уверен, что мои изменения пользовательских BB-кодов сработали бы, но выглядит так, что для phpBB 3.2+ достаточно отредактировать файл:

/script/import_scripts/phpbb3/support/bbcode/xml_to_markdown.rb

как указано выше, и добавить определение в формате:

def visit_<здесь ваш чувствительный к регистру пользовательский BB-код>(xml_node, md_node)
  # код для обработки элементов размещается здесь
end

Опять же, я ещё не тестировал это, но один очень распространённый пользовательский BB-код в phpBB, который отсутствует в версии xml_to_markdown.rb, которую я использовал, — это:

[YouTube]{Identifier}[/YouTube]

где {Identifier} — это значение параметра “v” из строки запроса URL YouTube.

Так что моя попытка новичка в Ruby добавить этот код в xml_to_markdown.rb выглядит так:

def visit_YouTube(xml_node, md_node)
      content = xml_node.content
      url = "https://www.youtube.com/watch?v=" + content
      md_node.text = "#{url}"
      md_node.prefix_linebreaks = md_node.postfix_linebreaks = 2
      md_node.prefix_linebreak_type = LINEBREAK_HTML
end

Наконец, при запуске скрипта импорта я дошёл только до этапа загрузки базы данных и получил следующую ошибку:

ERROR 1071 (42000) at line 1233035: Specified key was too long; max key length is 1000 bytes

Не уверен, является ли это проблемой движка БД — оригинал использует InnoDB — или чем-то другим, но предполагаю, что это будет исправлено в версии скрипта для phpBB 3.3.

2 лайка

Хорошо, я не мог оставить это без внимания.

Хотя, возможно, ошибку, которую я получил, можно было бы обработать скриптом импорта, мне кажется, что проблема кроется в структуре базы данных phpBB3 и в том, что моя кодировка базы данных — UTF8. При запуске скрипта импорта я получил следующую ошибку:

ERROR 1071 (42000) at line 1233035: Specified key was too long; max key length is 1000 bytes

Когда я посмотрел на строку 1233035 моего файла phpbb_mysql.sql (я использовал локальную копию дампа данных), я увидел следующее:

ALTER TABLE `phpbb_config`
  ADD PRIMARY KEY (`config_name`),
  ADD KEY `is_dynamic` (`is_dynamic`);

Изучив столбец config_name в таблице phpbb_config, я обнаружил, что он установлен как VARCHAR(255).

Благодаря этому посту на Stackoverflow, я узнал, что можно использовать «префиксный индекс», чтобы сократить длину ключа. Я протестировал это, и всё работает.

Для моей базы данных phpBB 3.3.8 затронутыми оказались четыре таблицы:

  • phpbb_config
  • phpbb_config_text
  • phpbb_migrations
  • phpbb_oauth_accounts

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

Рассчитайте минимальную длину префиксного индекса с помощью этого запроса:

SELECT
 ROUND(SUM(LENGTH(`config_name`)<10)*100/COUNT(`config_name`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`config_name`)<20)*100/COUNT(`config_name`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`config_name`)<50)*100/COUNT(`config_name`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`config_name`)<100)*100/COUNT(`config_name`),2) AS pct_length_100
FROM `phpbb_config`;

В моём случае结果显示, что 100% строк использовали менее 50 символов, поэтому я отредактировал файл дампа данных:

nano /var/discourse/shared/standalone/import/data/phpbb_mysql.sql

и использовал поиск Ctrl+W для следующей строки:

ALTER TABLE `phpbb_config`

затем заменил это:

ALTER TABLE `phpbb_config`
  ADD PRIMARY KEY (`config_name`),
  ADD KEY `is_dynamic` (`is_dynamic`);

на это:

ALTER TABLE `phpbb_config`
  ADD PRIMARY KEY (`config_name`(50)),
  ADD KEY `is_dynamic` (`is_dynamic`);

(50) здесь — это длина префиксного индекса.

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

SELECT
 ROUND(SUM(LENGTH(`config_name`)<10)*100/COUNT(`config_name`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`config_name`)<20)*100/COUNT(`config_name`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`config_name`)<50)*100/COUNT(`config_name`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`config_name`)<100)*100/COUNT(`config_name`),2) AS pct_length_100
FROM `phpbb_config_text`;

SELECT
 ROUND(SUM(LENGTH(`migration_name`)<10)*100/COUNT(`migration_name`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`migration_name`)<20)*100/COUNT(`migration_name`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`migration_name`)<50)*100/COUNT(`migration_name`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`migration_name`)<100)*100/COUNT(`migration_name`),2) AS pct_length_100
FROM `phpbb_migrations`;

SELECT
 ROUND(SUM(LENGTH(`provider`)<10)*100/COUNT(`provider`),2) AS pct_length_10,
 ROUND(SUM(LENGTH(`provider`)<20)*100/COUNT(`provider`),2) AS pct_length_20,
 ROUND(SUM(LENGTH(`provider`)<50)*100/COUNT(`provider`),2) AS pct_length_50,
 ROUND(SUM(LENGTH(`provider`)<100)*100/COUNT(`provider`),2) AS pct_length_100
FROM `phpbb_oauth_accounts`;

Вот строки поиска для остальных таблиц, чтобы сэкономить ваше время:

ALTER TABLE `phpbb_config_text`
ALTER TABLE `phpbb_migrations`
ALTER TABLE `phpbb_oauth_accounts`

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

#import_phpbb3.sh
The phpBB3 import is starting...

Loading existing groups...
Loading existing users...
Loading existing categories...
Loading existing posts...
Loading existing topics...

importing from phpBB 3.3.8

creating users
      722 / 5014 ( 14.4%)  [58 items/min]

Обновление:

Скрипт импорта завершился за 9 часов 28 минут. Слава богу за Screen. Этот скрипт великолепен!

Сейчас идёт постобработка.

Есть ли где-то лог вывода скрипта импорта, или мне следовало перенаправить его в файл?

3 лайка

Какую процедуру импортера phpbb3 следует использовать при запуске discourse_dev в контейнере Docker под WSL?

Я пробовал оба варианта: процедуру 1 (импорт с использованием контейнера Docker) и процедуру 2 (импорт в среде разработки). Ни один из них не сработал. Хотя в случае процедуры 1 скрипт выполнялся до конца, данные так и не попали в базу данных форума, несмотря на то, что множество запросов, судя по всему, успешно выполнялись по ходу работы. Возможно, задействована другая база данных, которая заполняется, поскольку импорт запускается в собственном контейнере, отдельном от контейнера discourse_dev?

В случае процедуры 2 просто невозможно выполнить сборку: она завершается ошибкой «Произошла ошибка при установке tiny_tds (2.1.5), и Bundler не может продолжить».

Стоит ли попробовать выполнить «стандартную установку» (не через Docker, не в режиме разработки) в WSL, а затем выполнить импорт с использованием Docker?

1 лайк

Именно это я и рекомендую. В последнее время я крайне редко выполняю миграцию в режиме разработки.

Кроме того, tiny_tds вам не понадобится, если вы используете не MSSQL, а MySQL/MariaDB.

1 лайк

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

2 лайка

Я успешно установил Discourse на новый VPS, используя стандартный процесс установки Docker. Затем я запустил процесс импорта согласно этим инструкциям, и скрипт завершил работу без ошибок. Я покинул контейнер и выполнил команду stop import, после чего получил сообщение:

''На диске, где расположен /var/lib/docker, доступно менее 5 ГБ свободного места. Для продолжения работы необходимо больше места.
Файловая система Размер Использовано Доступно % Монтировано на
/dev/vda1 24G 20G 2.7G 89% /

Хотите попытаться освободить место, удалив образы Docker и контейнеры в системе? (y/N)‘’

Освобождение места не дало дополнительных результатов. Как мне поступить дальше? Могу ли я безопасно удалить все файлы изображений, которые я загрузил в /data? Не уверен, нужны ли они ещё.

Спасибо.

1 лайк

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

1 лайк

Спасибо за этот совет, Джей.

На случай, если эти детали пригодятся другим, я удалил только файлы изображений, что освободило около 3,4 ГБ, и общий доступный объем составил 6,1 ГБ. После этого Sidekiq успешно справился с постобработкой. С тех пор дисковое пространство было увеличено еще на 20 ГБ.

Для справки: это был импорт форума phpBB версии 3.3.0, содержащего чуть более 73 000 сообщений в чуть более 8 000 темах и чуть более 1300 пользователей.

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

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

1 лайк

Когда я выполнял миграцию с phpBB 3.3.x, для финального импорта я перевёл сайт phpBB в «режим обслуживания», использовал rsync для обновления вложений, аватаров и смайликов, затем импортировал новый дамп данных и был вынужден перезапустить процесс импорта для выполнения финального запуска скрипта импорта, хотя до этого я уже завершил работу импорта.

@DonH, вы импортировали пароли из phpBB и настроили их работу с плагином Migrate Passwords?

2 лайка

Я не импортировал пароли phpBB по нескольким причинам. Я хотел избежать потенциальных конфликтов с плагинами и хотел заставить пользователей обновить свои пароли; эта миграция казалась хорошим способом (и хорошим поводом) для этого. Безопасность на хостинге phpBB обеспечивается компанией-хостинг-провайдером, но на новом VPS такой роскоши нет.

Для ясности: вы импортировали всю базу данных целиком в последний раз и не делали инкрементальное обновление?

1 лайк

По моему пониманию и опыту, если вы создадите дамп данных вашего форума phpBB (например, через phpMyAdmin), загрузите файл в каталог /var/discourse/shared/standalone/import/data, пересоберёте импорт, а затем снова выполните команду импорта, скрипт миграции не затронет уже импортированные учётные записи пользователей, сообщения и т. д., а обработает только те записи базы данных, которые ранее не были импортированы.

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

1 лайк

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

Не совсем понятно, о каких конфликтах плагинов вы говорите?

2 лайка

@RGJ Будет ли плагин migratepassword работать с phpBB 3.3?

Я в данный момент выполняю импорт с форума phpBB 3.3.8 и импортирую пароли, чтобы проверить это.

1 лайк

Как вы сможете выполнить миграцию с myBB?

1 лайк

Вы можете поискать myBB и тег #migration::tag, возможно, вы найдёте howto

2 лайка

Окей, спасибо за информацию!

1 лайк

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

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

2 лайка

Да, будет. Мы недавно добавили поддержку Argon2 в плагин.

4 лайка

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

1 лайк