将 IPB 3.1 论坛迁移到 Discourse

大家好,Discourse 社区,

我想分享我将 IPB 3.1 论坛导入 Discourse 2.1 的经验,希望这对其他人有所帮助。

社区简介:

  • 主题:Yii PHP 框架(代码相关讨论和支持)
  • 成员:约 2.6 万
  • 话题:约 6.4 万
  • 帖子:约 29.3 万

在一台拥有 16GB RAM 和 4 个 CPU 核心的机器上,导入过程耗时 27 小时 46 分钟。

导入要求:

  • 保留成员,但清理所有垃圾账户(约 25 万个账户,清理后保留约 2.6 万个)
  • 从网站实施 SSO(用户账户不由 Discourse 管理)
  • 保留话题、帖子和分类及其原始 URL,以便网络搜索结果仍然有效,并且来自 Stackoverflow 等平台的链接也能正常工作

这是基于 Migrating from Invision Power Board to Discourse - #23 by pfaffman 的,感谢 @pfaffman 在导入器方面所做的出色工作。

准备工作

从 IPB 导出数据

mysqldump <数据库名> > /tmp/ipb.sql
cd /var/www/yiiframework.com/forum/ && tar czvf uploads.tgz uploads/

将 SQL 转储文件和上传文件复制到新服务器,并将它们放入 /var/discourse/shared/standalone/
这里假设使用的是 Discourse 的简单 Docker 设置。

使用哪个脚本?

有两个导入脚本:ipboard.rbipboard3.rbipboard3.rb 脚本看起来非常粗糙,也不符合我们的表结构,所以我选择了 ipboard.rb

当前版本的 ipboard.rb 导入脚本对附件处理不佳,也没有转换代码标签,而这对我们非常重要,因为我们经常讨论 PHP 代码。因此,我对脚本进行了以下修改:

使上传的附件可用

导入脚本会将帖子附件替换为上传文件的 URL。
如果您打算在原有 URL 上保持 IPB 实例在线,只需指定上传目录的 URL(UPLOADS 是导入脚本的配置,见下文)即可完成:

UPLOADS="https://www.yiiframework.com/forum/uploads"

但我们导入 Discourse 是为了完全移除旧论坛,因此必须将上传文件放到其他地方。如果您在 Discourse 前面使用了 nginx 代理,可以配置它从服务器上的某个目录提供上传文件。将以下内容放入 nginx 配置的 server 部分:

location /ipb_uploads/ {
    alias /var/www/ipb_uploads/;
}

并按如下方式配置附件 URL(见下文):

UPLOADS="https://forum.yiiframework.com/ipb_uploads"

在 Discourse 容器中设置 MySQL

在 Discourse 应用容器中启动一个 bash shell:

docker exec -it app bash

在容器中安装 MySQL 并导入数据库:

apt-get install mysql-server mysql-client libmysqlclient-dev
service mysql start
echo "create database ipb" | mysql -uroot -p
mysql -uroot -p ipb < /shared/ipb.sql

当我第一次尝试导入以测试脚本时,导入 20 万个用户花了数天时间,其中我们知道有大量是垃圾账户,因此我们创建了一些 SQL 查询来删除从未发布过任何内容的账户:

请注意,我们将使用 SSO,因此删除的用户在登录时会被重新创建。
如果您不使用 SSO,删除用户的标准可能会有所不同。
您可以直接导入数据而不清理。

mysql -uroot -p
# 然后应用清理查询

接下来,我们需要为导入脚本安装依赖项:

cd /var/www/discourse
echo "gem 'mysql2'" >> Gemfile
echo "gem 'reverse_markdown'" >> Gemfile
bundle install --no-deployment

要允许数据库访问 Discourse 的 Postgres 数据库,请将 /etc/postgresql/10/main/pg_hba.conf 中的 peer 替换为 trust。注意,10 代表 Postgres 版本,如果您的设置中该文件不存在,请将 10 替换为您当前运行的 Postgres 版本。
重启 Postgres 以加载更改:service postgresql restart

导入

准备头像和上传文件:

mkdir /shared/imports
mv /shared/uploads.tgz /shared/imports
cd /shared/imports && tar xzvf uploads.tgz

运行导入器脚本:

cd /var/www/discourse
DB_HOST="localhost" DB_NAME="yiisite" DB_USER="root" DB_PW="root" TABLE_PREFIX="ipb_" IMPORT_AFTER="1970-01-01" UPLOADS="https://www.forum.yiiframework.com/ipb_uploads" AVATARS_DIR="/shared/imports/uploads/" USERDIR="user" bundle exec ruby script/import_scripts/ipboard.rb | tee import.log

请务必根据上述讨论调整 UPLOADS URL,因为上传文件将作为链接包含在帖子中,指向原始上传文件。

清理

如果一切顺利,使用 service mysql stopapt-get purge mysql-serverrm -rf /var/lib/mysql 进行清理。

设置 URL 重定向

为了保持现有论坛 URL 的完整性,导入脚本为每个话题创建了反映 IPB 中话题和分类 URL 的永久链接。
然而,这些永久链接并不涵盖话题中特定帖子的链接或不同页面的链接。
为了使这些 URL 正常工作,您需要配置一些 URL 重写规则,有以下三种选择:

  • 使用 Discourse 中的 permalink normalizations 设置删除 URL 中不必要的部分
  • 在 nginx 中配置重写规则,如果您在 Discourse 前面使用了 nginx 代理
  • 如果旧论坛位于与 Discourse 不同的 URL/主机上,您可以编写自定义脚本来重写 URL(这就是我所做的)

这是我们用于 URL 重定向的 PHP 代码:

相关资源

18 个赞

你好,

抱歉打扰这个旧话题,但我也在计划从 IPB (v3.4) 迁移到 Discourse,并且正在参考这个 #教程。所以我决定直接在这个话题下回复,而不是创建新话题。

mysql 包已不再包含在发行版中,因此我参考了 这篇指南,步骤如下:

wget http://repo.mysql.com/mysql-apt-config_0.8.13-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.13-1_all.deb
sudo apt update
sudo apt install mysql-server mysql-client libmysqlclient-deb
service mysql start

但随后我遇到了以下错误:
mysql: unrecognized service

请问有什么办法可以启动 MySQL 吗?

谢谢

在执行本应安装它的命令时是否出现了错误?我推荐进行一次谷歌搜索。

另外,你可能想使用 Discourse 自带的 ipb 脚本,而不是 OP 中引用的那个。

此脚本是否有任何更新,因为它无法与 IPB 4x 一起使用,并且与 Discourse 本身也不兼容,因为表的结构已更改而脚本保持不变

1 个赞

我现在正在进行 ipboard 导入。我不得不从一些查询中删除一些表和行。看起来它们有许多不同的表配置。

将 ipb 原始帖子转换为 markdown 也很棘手。

如果您有预算,可以联系我。我或许可以给您我为当前导入编写的代码,但它可能需要针对您的特定设置进行修改。

2 个赞

to help you, IPB 4x tables is as follow:

mysql> SHOW TABLES;
+-------------------------------------------+
| Tables_in_ipboard                         |
+-------------------------------------------+
| ipb_bbcode_mediatag                       |
| ipb_ccs_folders                           |
| ipb_cms_blocks                            |
| ipb_cms_containers                        |
| ipb_cms_custom_database_1                 |
| ipb_cms_custom_database_2                 |
| ipb_cms_database_categories               |
| ipb_cms_database_comments                 |
| ipb_cms_database_fields                   |
| ipb_cms_database_fields_reciprocal_map    |
| ipb_cms_database_fields_thumbnails        |
| ipb_cms_database_reviews                  |
| ipb_cms_database_revisions                |
| ipb_cms_databases                         |
| ipb_cms_folders                           |
| ipb_cms_media                             |
| ipb_cms_media_folders                     |
| ipb_cms_page_database_map                 |
| ipb_cms_page_widget_areas                 |
| ipb_cms_pages                             |
| ipb_cms_template_conflicts                |
| ipb_cms_templates                         |
| ipb_cms_url_store                         |
| ipb_core_achievements_log                 |
| ipb_core_achievements_log_milestones      |
| ipb_core_achievements_rules               |
| ipb_core_acp_notifcations_dismissals      |
| ipb_core_acp_notifications                |
| ipb_core_acp_notifications_preferences    |
| ipb_core_acp_search_index                 |
| ipb_core_acp_tab_order                    |
| ipb_core_acronyms                         |
| ipb_core_admin_login_logs                 |
| ipb_core_admin_logs                       |
| ipb_core_admin_permission_rows            |
| ipb_core_advertisements                   |
| ipb_core_alerts                           |
| ipb_core_alerts_seen                      |
| ipb_core_announcements                    |
| ipb_core_anonymous_posts                  |
| ipb_core_api_keys                         |
| ipb_core_api_logs                         |
| ipb_core_api_webhook_fires                |
| ipb_core_api_webhooks                     |
| ipb_core_applications                     |
| ipb_core_approval_queue                   |
| ipb_core_archive_log                      |
| ipb_core_archive_restore                  |
| ipb_core_attachments                      |
| ipb_core_attachments_map                  |
| ipb_core_automatic_moderation_pending     |
| ipb_core_automatic_moderation_rules       |
| ipb_core_automatic_moderation_types       |
| ipb_core_badges                           |
| ipb_core_banfilters                       |
| ipb_core_bulk_mail                        |
| ipb_core_cache                            |
| ipb_core_club_pages                       |
| ipb_core_clubs                            |
| ipb_core_clubs_fields                     |
| ipb_core_clubs_fieldvalues                |
| ipb_core_clubs_memberships                |
| ipb_core_clubs_node_map                   |
| ipb_core_contact_verify                   |
| ipb_core_content_featured                 |
| ipb_core_content_meta                     |
| ipb_core_deletion_log                     |
| ipb_core_dev                              |
| ipb_core_edit_history                     |
| ipb_core_editor_stored_replies            |
| ipb_core_email_templates                  |
| ipb_core_emoticons                        |
| ipb_core_error_logs                       |
| ipb_core_file_logs                        |
| ipb_core_file_storage                     |
| ipb_core_files                            |
| ipb_core_files_temp                       |
| ipb_core_follow                           |
| ipb_core_follow_count_cache               |
| ipb_core_geoip_cache                      |
| ipb_core_googleauth_used_codes            |
| ipb_core_group_promotions                 |
| ipb_core_groups                           |
| ipb_core_hooks                            |
| ipb_core_hooks_files                      |
| ipb_core_ignored_users                    |
| ipb_core_incoming_emails                  |
| ipb_core_inline_messages                  |
| ipb_core_ips_bulletins                    |
| ipb_core_item_markers                     |
| ipb_core_item_member_map                  |
| ipb_core_item_redirect                    |
| ipb_core_item_statistics_cache            |
| ipb_core_javascript                       |
| ipb_core_leaders                          |
| ipb_core_leaders_groups                   |
| ipb_core_like_cache                       |
| ipb_core_log                              |
| ipb_core_login_failures                   |
| ipb_core_login_handlers                   |
| ipb_core_login_links                      |
| ipb_core_login_methods                    |
| ipb_core_mail_error_logs                  |
| ipb_core_member_badges                    |
| ipb_core_member_history                   |
| ipb_core_member_privacy_actions           |
| ipb_core_member_ranks                     |
| ipb_core_member_recognize                 |
| ipb_core_member_status_replies            |
| ipb_core_member_status_updates            |
| ipb_core_members                          |
| ipb_core_members_feature_seen             |
| ipb_core_members_known_devices            |
| ipb_core_members_known_ip_addresses       |
| ipb_core_members_logins                   |
| ipb_core_members_warn_actions             |
| ipb_core_members_warn_logs                |
| ipb_core_members_warn_reasons             |
| ipb_core_menu                             |
| ipb_core_message_posts                    |
| ipb_core_message_topic_user_map           |
| ipb_core_message_topics                   |
| ipb_core_moderator_logs                   |
| ipb_core_moderators                       |
| ipb_core_modules                          |
| ipb_core_notification_defaults            |
| ipb_core_notification_preferences         |
| ipb_core_notifications                    |
| ipb_core_notifications_pwa_keys           |
| ipb_core_notifications_pwa_queue          |
| ipb_core_oauth_authorize_prompts          |
| ipb_core_oauth_clients                    |
| ipb_core_oauth_server_access_tokens       |
| ipb_core_oauth_server_authorization_codes |
| ipb_core_output_cache                     |
| ipb_core_permission_index                 |
| ipb_core_pfields_content                  |
| ipb_core_pfields_data                     |
| ipb_core_pfields_groups                   |
| ipb_core_plugins                          |
| ipb_core_points_log                       |
| ipb_core_polls                            |
| ipb_core_post_before_registering          |
| ipb_core_profanity_filters                |
| ipb_core_profile_completion               |
| ipb_core_profile_steps                    |
| ipb_core_question_and_answer              |
| ipb_core_queue                            |
| ipb_core_ratings                          |
| ipb_core_rc_author_notification_text      |
| ipb_core_rc_comments                      |
| ipb_core_rc_index                         |
| ipb_core_rc_reports                       |
| ipb_core_reactions                        |
| ipb_core_referral_banners                 |
| ipb_core_referrals                        |
| ipb_core_reputation_index                 |
| ipb_core_reputation_leaderboard_history   |
| ipb_core_reputation_levels                |
| ipb_core_rss_export                       |
| ipb_core_rss_import                       |
| ipb_core_rss_imported                     |
| ipb_core_s3_deletions                     |
| ipb_core_saved_charts                     |
| ipb_core_search_index                     |
| ipb_core_search_index_item_map            |
| ipb_core_search_index_tags                |
| ipb_core_security_answers                 |
| ipb_core_security_questions               |
| ipb_core_seo_meta                         |
| ipb_core_sessions                         |
| ipb_core_share_links                      |
| ipb_core_sitemap                          |
| ipb_core_social_promote                   |
| ipb_core_social_promote_content           |
| ipb_core_social_promote_sharers           |
| ipb_core_soft_delete_log                  |
| ipb_core_solved_index                     |
| ipb_core_spam_service_log                 |
| ipb_core_spam_whitelist                   |
| ipb_core_statistics                       |
| ipb_core_store                            |
| ipb_core_stream_subscriptions             |
| ipb_core_streams                          |
| ipb_core_sys_conf_settings                |
| ipb_core_sys_cp_sessions                  |
| ipb_core_sys_lang                         |
| ipb_core_sys_lang_words                   |
| ipb_core_sys_login                        |
| ipb_core_sys_settings_titles              |
| ipb_core_sys_social_group_members         |
| ipb_core_sys_social_groups                |
| ipb_core_tags                             |
| ipb_core_tags_cache                       |
| ipb_core_tags_perms                       |
| ipb_core_tasks                            |
| ipb_core_tasks_log                        |
| ipb_core_theme_conflict                   |
| ipb_core_theme_content_history            |
| ipb_core_theme_css                        |
| ipb_core_theme_resources                  |
| ipb_core_theme_settings_fields            |
| ipb_core_theme_settings_values            |
| ipb_core_theme_templates                  |
| ipb_core_themes                           |
| ipb_core_upgrade_history                  |
| ipb_core_validating                       |
| ipb_core_view_updates                     |
| ipb_core_voters                           |
| ipb_core_widget_areas                     |
| ipb_core_widget_trash                     |
| ipb_core_widgets                          |
| ipb_custom_bbcode                         |
| ipb_forums_answer_ratings                 |
| ipb_forums_archive_posts                  |
| ipb_forums_archive_rules                  |
| ipb_forums_forums                         |
| ipb_forums_posts                          |
| ipb_forums_question_ratings               |
| ipb_forums_topic_mmod                     |
| ipb_forums_topics                         |
| ipb_forums_view_method                    |
| ipb_nexus_alternate_contacts              |
| ipb_nexus_billing_agreements              |
| ipb_nexus_cart_uploads                    |
| ipb_nexus_coupons                         |
| ipb_nexus_customer_addresses              |
| ipb_nexus_customer_cards                  |
| ipb_nexus_customer_fields                 |
| ipb_nexus_customer_spend                  |
| ipb_nexus_customers                       |
| ipb_nexus_donate_goals                    |
| ipb_nexus_donate_logs                     |
| ipb_nexus_eom                             |
| ipb_nexus_fraud_rules                     |
| ipb_nexus_invoice_tracker                 |
| ipb_nexus_invoices                        |
| ipb_nexus_licensekeys                     |
| ipb_nexus_member_subscription_packages    |
| ipb_nexus_member_subscriptions            |
| ipb_nexus_notes                           |
| ipb_nexus_package_base_prices             |
| ipb_nexus_package_fields                  |
| ipb_nexus_package_filters                 |
| ipb_nexus_package_filters_map             |
| ipb_nexus_package_filters_values          |
| ipb_nexus_package_groups                  |
| ipb_nexus_package_images                  |
| ipb_nexus_packages                        |
| ipb_nexus_packages_ads                    |
| ipb_nexus_packages_products               |
| ipb_nexus_paymethods                      |
| ipb_nexus_payouts                         |
| ipb_nexus_product_options                 |
| ipb_nexus_purchases                       |
| ipb_nexus_referral_rules                  |
| ipb_nexus_reviews                         |
| ipb_nexus_ship_orders                     |
| ipb_nexus_shipping                        |
| ipb_nexus_support_default_content         |
| ipb_nexus_support_departments             |
| ipb_nexus_support_fields                  |
| ipb_nexus_support_notify                  |
| ipb_nexus_support_ratings                 |
| ipb_nexus_support_replies                 |
| ipb_nexus_support_request_log             |
| ipb_nexus_support_requests                |
| ipb_nexus_support_severities              |
| ipb_nexus_support_staff_dpt_order         |
| ipb_nexus_support_staff_preferences       |
| ipb_nexus_support_statuses                |
| ipb_nexus_support_stock_actions           |
| ipb_nexus_support_streams                 |
| ipb_nexus_support_tracker                 |
| ipb_nexus_support_views                   |
| ipb_nexus_tax                             |
| ipb_nexus_transactions                    |
| ipb_rc_reports_index                      |
| x_utf_ipb_convert_session                 |
| x_utf_ipb_convert_session_tables          |
+-------------------------------------------+