将Phorum论坛迁移到Discourse

If you have an old Phorum forum and thinking to migrate to Discourse, then this tutorial is for you. The process is straightforward and we will be using the official Phorum Importer script. Let’s get started.

On a high level, we will do the following.

  • Preparing the local development environment.
  • Exporting the database from the production environment.
  • Importing the production database to a local Discourse instance.
  • Running the Phorum importer script.

What can be migrated

  • Categories
    • Every forums and folders => Root category
  • Topics & Posts
  • Users (with the following attributes)
    • banned status
    • username
    • real name => name
    • email
    • admin status
    • date added
    • last active

Preparing Local Development Environment

Follow one of these guides to install Discourse itself and consult this guide if you have any problems.

Install MySQL DB server;

Ubuntu 18.04:

$ sudo apt update
$ sudo apt install mysql-server -y

After finishing installing MySQL, check its status:

$ systemctl status mysql.service

If it is not running, run the following:

$ sudo systemctl start mysql

MacOS:

$ brew install mysql@5.7
$ echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

Check the services status:

$ brew services list

You should see something like this:

...
mysql@5.7         started
...

Otherwise, run the following and check again:

$ brew services start mysql@5.7

For Windows, you can follow the official installation guide.

This environment will be our Discourse server.

Exporting The Database from Production Environment:

Export the production database (from Phorum production server):

$ mysqldump -u USER_NAME -p DATABASE_NAME > phorum_dump.sql

Copy the database dump to the Discourse server.

:bulb: Use scp or rsync to copy the database. And of course, you can gzip it first.

Importing The Production Database to Discourse server

On Discourse server, Create a database:

$ mysql -u root

:bulb: If your database user has a password you should use: mysql -u root -p then type your password.

mysql> CREATE DATABASE phorum;

Make sure that the database is created:

mysql> SHOW DATABASES;

You should see something like this:

+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| phorum             |
| sys                |
+--------------------+
5 rows in set (0.04 sec)

This is an empty database. Our next step is to import the production database into it.

$ mysql -u root phorum < phorum_dump.sql

While we are here, let’s get the table prefix. We will need it later:

$ mysql -u root
mysql> USE phorum;
mysql> SHOW TABLES;

You will see something like this:

+---------------------------+
| Tables_in_phorum          |
+---------------------------+
| pw_banlists           |
| pw_files              |
| pw_forum_group_xref   |
| pw_forums             |
| pw_groups             |
| pw_messages           |
| pw_messages_edittrack |
| pw_pm_buddies         |
| pw_pm_folders         |
| pw_pm_messages        |
| pw_pm_xref            |
| pw_search             |
| pw_settings           |
| pw_subscribers        |
| pw_user_custom_fields |
| pw_user_group_xref    |
| pw_user_newflags      |
| pw_user_permissions   |
| pw_users              |
+---------------------------+
19 rows in set (0.00 sec)

From the output above you can see that the prefix is pw_.

Running Phorum Importer Script

First, install the importer dependencies:

$ cd ~/discourse
$ echo "gem 'mysql2', require: false" >> Gemfile
$ bundle install

Now let’s configure the script to fits our requirements. In our example this will do:

PHORUM_DB = "phorum"
TABLE_PREFIX = "pw_"
BATCH_SIZE = 1000

# ...

host: "localhost",
username: "root",
password: "", # Change this if you have a password for MySQL database
database: PHORUM_DB

If you want to create a url redirecting, then you should uncomment the following:

# categories.each do |category|
#   Permalink.create(url: "list.php?#{category['id']}", category_id: category_id_from_imported_category_id(category['id'].to_i))
# end

#...

# results.each do |post|
#   if post['parent_id'] == 0
#     topic = topic_lookup_from_imported_post_id(post['id'].to_i)
#     Permalink.create(url: "read.php?#{post['category_id']},#{post['id']}", topic_id: topic[:topic_id].to_i)
#   end
# end

It will be like this:

categories.each do |category|
  Permalink.create(url: "list.php?#{category['id']}", category_id: category_id_from_imported_category_id(category['id'].to_i))
end

#...

results.each do |post|
  if post['parent_id'] == 0
    topic = topic_lookup_from_imported_post_id(post['id'].to_i)
    Permalink.create(url: "read.php?#{post['category_id']},#{post['id']}", topic_id: topic[:topic_id].to_i)
  end
end

Run the importer with a clean Discourse instance:

bundle exec rake db:drop db:create db:migrate
bundle exec ruby script/import_scripts/phorum.rb

The importer will connect to the MySQL server and migrates our Phorum database to Discourse database.

Start Discourse server after the importer finish importing:

$ bundle exec rails server

Start Sidekiq to process the migrated data:

$ bundle exec sidekiq

:bulb: You can monitor sidekiq progress at http://localhost:3000/sidekiq/queues.

Setup your Discourse production server by following this tutorial.

Perform a backup for Discourse database and upload it to your Discourse production server by following this tutorial.

It’s done :tada:

7 个赞

I’m about to start work on migrating a Phorum forum to Discourse. I would like to preserve files attached to posts (mostly pictures). Looks like this is not supported in the current migration script. Has anyone noodled on that already?

1 个赞

I’ve made a couple tweaks to the migration script for “phorum” including migrating attachments/files/uploads. The pull request is here:

1 个赞

感谢提供的脚本!

不过,我觉得手册相当粗糙且不清楚。我不得不参考例如 Xenforo 迁移指南 来真正理解你在这里的建议。让我添加一些缺失的步骤:

  • 运行 Discourse
  • 从原始 Phorum 创建 mysqldump - 一切都很清楚,一切都很好。
  • 将数据库转储复制到 Discourse 文件夹 docker cp /path/to/backup/phorum_db.sql.gz app:/shared/phorum_db.sql.gz(假设 app 是标准的容器名称)
    这里是缺失的部分:
  • 实际进入 Discourse Docker 容器并在那里安装 MySQL:
docker exec -it app bash
apt-get update && apt-get upgrade
# pv 仅用于方便显示进度,lsb-release 是某些东西必需的
apt-get install -y lsb-release pv mariadb-server mariadb-client libmariadb-dev
service mariadb start

请注意,MySQL 安装有点棘手,但 Mariadb 应该同样适用。

然后创建一个数据库:mysqlCREATE database phorum

然后从备份中填充它:pv phorum_db.sql.gz | gunzip | mysql phorum(如果你的转储是纯 sql,则不需要 gunzip)。

为 Ruby 添加 MySql 支持:

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

修改迁移脚本中的数据(数据库凭据、前缀、永久链接):

nano /var/www/discourse/script/import_scripts/phorum.rb

然后回到原始帖子的指南,一切都很好:

运行带有干净 Discourse 实例的导入器:

git config --global --add safe.directory /var/www/discourse
bundle exec ruby script/import_scripts/phorum.rb

如果你的 Discourse 数据库不是很干净,最好事先用 bundle exec rake db:drop db:create db:migrate 清理它。

如果出现“PG::ConnectionBad: connection to server on socket “/var/run/postgresql/.s.PGSQL.5432” failed: FATAL: Peer authentication failed for user “discourse” (PG::ConnectionBad)”错误:

  1. 如果你收到错误“‘Peer authentication failed for user “discourse”’”
  2. 编辑文件 /etc/postgresql/13/main/pg_hba.conf
  3. 将所有‘peer’更改为‘trust’并保存文件
  4. 重新加载 postgres 服务器:/etc/init.d/postgresql reload(或者可能是 psql -U postgres -c "SELECT pg_reload_conf();",但这有时对我不起作用)

首先运行用户迁移,这可能相对较慢(根据脚本输出,约为 1.2k 用户/分钟。我有 100k 用户,所以…)。然后它会创建类别并开始迁移消息和主题(速度相同,约 1.2k/分钟),但此时你已经可以访问网站并查看它的外观了。

对于像 Phorum 这样古老的引擎来说,这似乎比我预期的要顺畅得多。似乎没有迁移私人消息(PM),但这至少对我来说不是障碍。

再次感谢脚本和付出的努力!

要为如此复杂且涵盖所有步骤的内容编写指南非常困难。弄清楚某个特定用户可能需要被告知哪些部分很复杂。很高兴找到了另一份包含缺失部分的指南。

你或许可以包含 mysql 模板来安装 mysql,或者你也可以通过某种方式访问已安装的 mysql 服务器(我通常就是这么做的)。

如果你愿意,可以查看一些导入 PM 的其他脚本作为示例。