博客迁移札记——第二日

第二日

新建好只是第一步,更重要的,是如何把原来的东西原原本本地搞过来。本着最小手工工作量的原则,我在想,是不是只要把数据库表全复制过来就好了呢?WordPress的安装目录下,有没有什么别的东西要复制过来呢?最少需要复制哪些呢?这些问题在网上是找不到完整的答案的。因为具体情况是不一样的。而且,还是那个问题,考虑到开源界10年的卓越贡献。

具体做哪些先放一下,先把前期工作准备好。比如老的主机上的图片,怎么搞到新的服务器上呢?像昨天那样用scp传是不行的。主要是因为云虚拟主机根本没有开ssh,其次呢,是因为这么手工一个个跑命令也不是个事儿。虽然也可以写脚本,但是这种脚本的可重用性就比较差,我下次再要传别的文件呢?再写个脚本?给脚本改参数?都不好。传文件这种事儿就应该是一键完成的。考虑到云虚拟主机只能通过FTP传,天然的直接方案就是,在新的ECS上也搭建一个FTP服务器。

说干就干。命令如下:

dnf install vsftpd
systemctl start vsftpd
systemctl enable vsftpd

安装简单,配置起来可就没那么简单了。首先,得有一个特别的ftp用户,比如就叫ftpuser,然后这个用户得能访问/var/www/html这个文件夹。然后还得和Apache不打架。然后,还不能有安装隐患。

创建用户并配置相关权限的命令如下(主要参考了这里):

adduser ftpuser                   #创建用户
passwd ftpuser                    #设置密码
usermod -d /var/www -m ftpuser    #设置用户主目录
usermod -a -G apache ftpuser      #为用户添加组

其中apache是Apache HTTPD服务用的一个用户组。而/var/www默认的Owner和Group是root(因为安装Apache的时候用的root)。所以还需要把/var/www的Owner和Group都改成apache,以便ftpuser可以访问并修改里面的文件。

chgrp -R apache /var/www         #更改文件夹所属组
chmod -R g+w /var/www            #更改组权限

这些都配置了之后,发现从ECS主机上,本地是可以连上去的。但是从Mac上就连不上去,最后Google半天,发现是Passive Mode的连接模式,

最终,对/etc/vsftpd/vsftpd.conf这个文件的改动是这个样子的。

[user@host vsftpd]$ diff vsftpd.conf_back vsftpd.conf
124c125,128
<
---
> pasv_addr_resolve=YES
> pasv_address=<PUBLIC_IP_V4>
> pasv_min_port=xxxxx
> pasv_max_port=yyyyy

然后,去ECS上开如下几个端口:21,xxxxx/yyyyy。

关于pasv_min/max_port的更多解释可以参考官方文档:

man vsftpd.conf

然后,下载个FileZilla,就可以连上去了。但是新发现的一个问题是,客户端可以访问到整个服务器上的所有文件。然后又是一轮Google:how to restrict ftp user to a directory?然后发现和chroot的配置相关。顺便了解了一下chroot是个啥。于是又要改/etc/vsftpd/vsftpd.conf作如下配置变更:

[user@host vsftpd]$ diff vsftpd.conf_back vsftpd.conf
100c100,101
< #chroot_local_user=YES
---
> chroot_local_user=YES
> allow_writeable_chroot=YES

这样,就可以把客户端的访问权限限制在/var/www里了。

下一个问题是,需要传哪些文件呢?图片文件在哪里呢?这里展示了WordPress的目录结构,可以看名字猜一下,哪些放的是WordPress自己的代码、样式,哪些放的是用户数据?哪些需要传到新的站点上呢?

[user@host blog]# tree -L 2 -d .
.
|-- wp-admin
|   |-- css
|   |-- images
|   |-- includes
|   |-- js
|   |-- maint
|   |-- network
|   `-- user
|-- wp-content
|   |-- languages
|   |-- plugins
|   |-- themes
|   |-- upgrade
|   `-- uploads
`-- wp-includes
    |-- assets
    |-- block-patterns
    |-- blocks
    |-- block-supports
    |-- certificates
    |-- css
    |-- customize
    |-- fonts
    |-- ID3
    |-- images
    |-- IXR
    |-- js
    |-- php-compat
    |-- PHPMailer
    |-- pomo
    |-- random_compat
    |-- Requests
    |-- rest-api
    |-- SimplePie
    |-- sitemaps
    |-- sodium_compat
    |-- Text
    |-- theme-compat
    `-- widgets

这里顺便问个问题,请观察这几个文件夹的名字,问,文件夹的命名风格是什么?

    |-- IXR
    |-- rest-api
    |-- SimplePie
    |-- sitemaps
    |-- sodium_compat

答:Free Style(自由风格)因为这是Freeware(自由软件)。

好,在不看代码的情况下,我们只能通过文件夹的名字盲猜其用途,然后决定要不要复制到新服务器上。当然,另一个简单的方式是,全部都复制。但是显然是不行的,因为至少wp-config.php这个文件里,就包括了针对特定服务器的配置。覆盖过去,直接数据库就连不上了。所以不能无脑地全复制。我们先按常识自己挑一些:

  • uploads:上传的图片和视频等。这
  • themes:主题文件。老的WordPress有些老的主题,新的默认只安装新的。当然,也可以在新网站上重新安装这些主题,而不用复制过去。
  • languages:本地化。本来这个东西应该是新的安装也自带的,但是非常神奇的是,新版WordPress里少一个zh_CN.php文件,这个文件还是很有用的。于是就只能从老版复制过来。

比如,如何做云端数据库全表迁移?更具体些,是从云虚拟主机的数据库,迁移到ECS自建数据库上。

在云虚拟主机的页面上,我找到了一个叫DMS的工具。可以管理阿里云的所有数据库的。而且还有桌面版。而且还支持MacOS。这样的话,也就不需要安装phpMyAdmin了,毕竟服务器资源有限,能少安装东西就少安装东西,CPU得用来跑业务,而不是用来跑工具,哪怕是辅助,能不长驻就不要长驻。

但是在尝试从Mac连接到数据库的时候出了问题:连不上。好说,无非又要开ECS的端口了。

再试,又失败了,还是一个新品种的错误:不允许用户从远程登录。还记得前一天是如何创建的数据库用户的吗?

CREATE USER `admin`@`localhost` IDENTIFIED BY 'pass';

这里的localhost的意思就是只允许用户从本地登录。于是我们得让这个用户可以远程访问。也不难找到现成的作业来抄。

CREATE USER 'admin'@'%' IDENTIFIED BY 'pass';
GRANT ALL ON *.* TO 'admin'@'%';
FLUSH PRIVILEGES;

然后就顺序连上ECS的数据库了。然而,在连云虚拟主机的MySQL实例的时候,又出状况了。DMS要求我先建立一个本地网关,然后把云虚拟主机的MySQL实例,作为第三方数据库实例注册到DMS上。

我就无语了。这里的故事背景是:云虚拟主机业务,其实是阿里收购的万网。敢情阿里的收购,收完就完了,根本不当自己人对待。哪怕会影响用户体验。

在DMS上试了好几回全库数据导出和SQL执行,最终把数据库里的数据全迁移过程了。遇到的坑包括:

原数据库(MySQL 5.7)中存在’0000-00-00 00:00:00.000’这样的日期值,新的数据库(MySQL 8.0)是插入不进去的,导致数据导入失败。

所以得先把现有数据,在老的服务上修好。SQL如下:

UPDATE `wp_posts`
   SET `post_date_gmt`= DATE_SUB(`post_date`, INTERVAL 8 HOUR)
 WHERE `post_date_gmt`= '0000-00-00 00:00:00';

UPDATE `wp_posts`
   SET `post_modified_gmt`= DATE_SUB(`post_modified`, INTERVAL 8 HOUR)
 WHERE `post_modified_gmt`= '0000-00-00 00:00:00';

注意,上面有个Hardcode的数字8。是东八区的八。如果你在别的时区,自己手工改下再执行哈。

把数据导入到了新的库上之后呢,要把数据里的原来的URL全部替换成新的,SQL如下:

UPDATE `wp_posts`
 SET guid = REPLACE(guid, 'www.hugogu.cn' ,'blog.hugogu.cn/blog');

UPDATE `wp_posts`
 SET post_content = 
    REPLACE(post_content, 'www.hugogu.cn' ,'blog.hugogu.cn/blog');

UPDATE wp_options 
 SET option_value = 
    REPLACE(option_value, 'www.hugogu.cn' ,'blog.hugogu.cn/blog') 
 WHERE option_name = 'home' OR option_name = 'siteurl';

更新过程中,还有一个小插曲,看到home和siteurl的值是一样的,我强迫症就犯了,开始脑补他们可能有什么不同以及怎么用。脑补了一套理论之后就顺手把siteurl改成了自己感觉更合理的’blog.hugogu.cn’。然后刷新页面一看,500了。所有页面全挂。

然后Google了一下这个问题,确认了这是WordPress苦手普遍都会犯的错误,而不是WordPress自己的问题。便在DMS上直接手工改数据库上的数据把值改回来。但是其实,通过改这个siteurl以求解决的那两个问题还是没有解决:

  1. 通过blog.hugogu.cn访问博客空间,而非blog.hugogu.cn/blog。如果WordPress的配置解决不了这个问题,那就意味着需要改Apache的配置了。这非常让人沮丧。这个后面会介绍。
  2. WordPress为什么要让siteurl可以配置?这个配置是用来解决什么问题的?不过这个问题不在WordPress迁移的主流程上,就不继续深入研究了。

现在数据迁移好了,可以通过blog.hugogu.cn/blog来访问了,但是这个URL本身就特别的不专业——blog这个词出现了两次。我们现在来想办法把这个词干掉。从Apache提供的能力上来看,感觉有很多方式。然而我想找的是最合理最简洁的方式去做。

还有一个问题是Permalinks也始终不工作。网上可以找到的方案基本都会提到三个方案,三个方案都试过了。一直折腾到半夜都没有解决这个问题。

不过想想至少内容都有了,只是样式和配置上和原来的还不太一样。这是第二日。

发表回复