在部署多站点 WordPress 中重用核心部分文件

问题背景

首先情况是这样的:我有一个服务器,上面部署了 nginx,然后通过设置不同的虚拟主机,对不同的域名映射到了不同的 wordpress 实例,各自对应于运营的一个网站。

最基本的情况是,每个 wordpress 有一个单独的文件夹,有一个单独 db。

但是这样的话,会有一个问题,很多部分其实是重复的,在我的实现中,每个站点之间的不同,就是应用的主题(由我自己开发,各自不同)不一样,使用的插件集合不一样,配置文件(仅仅是 wp-config.php)不一样。

如此一来,其余的很多部分(主要是 wordpress 的 Kernel 程序文件),都是重复的,平时已经占有磁盘空间,备份的时候免不了也会另备一份。

以前的处理:一个不好的实践

OK,那么前面说到,其实最基本的,每个站来说不同的就是数据库,还有应用的模板,当时在网上找了一个这样的解法:

我可以让 nginx 把所有的域名解析到同一个 wordpress 路径,只部署一个 wordpress 文件夹的实例,然后在 wp-config.php 上面来判断:

来看一下 wp-config.php 的有效部分:

/** WordPress数据库的名称 */
define('DB_NAME', 'db_mysite1');

/** MySQL数据库用户名 */
define('DB_USER', 'www-data');

/** MySQL数据库密码 */
define('DB_PASSWORD', 'user-password');

/** MySQL主机 */
define('DB_HOST', 'localhost');

/** 创建数据表时默认的文字编码 */
define('DB_CHARSET', 'utf8');

/** 数据库整理类型。如不确定请勿更改 */
define('DB_COLLATE', '');

OK,实际上,看起来,wp-config.php 的作用只是定位数据库的位置,我们可以通过判断条件来实现站点数据的分流:

if($_SERVER['HTTP_HOST'] == 'www.mysite1.com') {
    define('DB_NAME', 'db_mysite1');
} elseif($_SERVER['HTTP_HOST'] == 'www.mysite2.com') {
    define('DB_NAME', 'db_mysite2');
} elseif($_SERVER['HTTP_HOST'] == 'www.mysite3.com') {
    define('DB_NAME', 'db_mysite3');
    // ...
}

按照这种方案,用不同的域名访问过来,虽然从 nginx 进去的是同一个虚拟主机,但是解析到 wordpress 实例启动的时候,连接到的数据库是不一样的。由于当前主题的所有配置,包括使用哪个模板,哪些插件都是记录在数据库里面的,因此只要数据库能够动态指定,就可以达到多站的效果。

当然,这只是一个思路,我们当然还可以通过设置不同的 $table_prefix 来达到同样的效果(将不同的站的数据塞到同一个数据库里面,前缀不同。)这样本质上是一样的。

if($_SERVER['HTTP_HOST'] == 'www.mysite1.com') {
    $table_prefix  = 'site1_';
} elseif($_SERVER['HTTP_HOST'] == 'www.mysite2.com') {
    $table_prefix  = 'site2_';
} elseif($_SERVER['HTTP_HOST'] == 'www.mysite3.com') {
    $table_prefix  = 'site3_';
    // ...
}

OK,这是可行的,那是时候说一下优点和缺点:

优点

实现了最大的文件重用,那些核心文件(可能会被升级,但绝不会手动改的,因此所有站都是一样的)部分,例如 /wp-admin//wp-includes/ 的部分可以完全重用,另外,所有站的插件以及主题都全部堆在 /wp-content/ 里面,同样的插件,也是只放一份就 OK 了。

备份的时候也是,直接一包搞定,省事,要是加站,还省却了重新配置 nginx 虚拟主机的麻烦。

缺点

这个也是后来用了之后才发现:

第一个,不同站之间的静态文件引用是混在一起的,例如我有 10 个站,每个站一个主题,那么每个站虽然只用其中一个,但是在后台里面是可以看到别的站的主题的!一旦误操作,或者恶意修改了别人的站的代码,根本控制不了,后台存在风险;

第二个,所有的附件上传也是通的,这样一来不同的站上面上传的附件被搅在了一起,无法分开,哪天客户说要导个备份,要把属于各自的文件分解开来,还除了手动还真是没招;

第三个,有些插件是会需要改到 wp-config.php 的,例如 wp-super-cache,你在编辑插件的同时,不仅仅是动了数据库,还会在 wp-config.php 里面定义一些诸如是否启用缓存的常量云云。这时候,这种配置,也会在不同的站之间串,无法控制,最终被迫所有的站都不使用缓存。

久而久之,觉得这点现状必须改变。

一个失败的尝试

ok,那么既然混在一起行不通,那么还是隔离开为好:

  1. 每个站配置一个 nginx 的虚拟主机配置文件;
  2. 每个站设置一个 wordpress 程序目录;
  3. 每个站独立的 wp-config.php 文件(第2点满足自然如此)

然后重用方面,只需要保证两个核心文件夹能够复用就可以了。

再直白一点,只需要把 /wp-admin//wp-includes/ 两个文件夹做成引用就万事大吉了。

怎么引用?通过操作系统。

那么做一个目录的软链接?硬链接是不可以在目录上面做的。

那么 OK,我做了这一步:

cd /var/www/site1
rm -rf wp-admin
rm -rf wp-includes
cd /var/www/site2
rm -rf wp-admin
rm -rf wp-includes
ln -s /var/www/wordpress/wp-admin /var/www/site1/
ln -s /var/www/wordpress/wp-includes /var/www/site1/
ln -s /var/www/wordpress/wp-admin /var/www/site2/
ln -s /var/www/wordpress/wp-includes /var/www/site2/

这样相当于是一个快捷方式。

结果网站跑不起来了。

经过检查,发现了问题的所在,因为通过软连接目录,目录里面的文件,它的路径还是他的原始位置。

于是有些在 /wp-admin 里面的代码,一运行,路径就错了。

最终的方案

然后我再 Stack Overflow 上面问了这个问题

http://stackoverflow.com/q/28260219/2544762

原来利用 OS 本身,可以用挂载的方式实现文件夹的引用。

cd /var/www/site1
mkdir wp-admin
mount --bind /var/www/wordpress/wp-admin /var/www/site1/wp-admin

通过这种方式来进行文件夹的引用。

不过有一点,在备份的时候,仍旧需要通过手动忽略 /wp-admin//wp-includes/ 的方式来减小备份集的体积。


先说到这里,把折腾一个周日的事情记录下来,大家以后遇到同样的事情可以参照。


【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2015/02/wordpress-kenel-reuse.html【在部署多站点 WordPress 中重用核心部分文件】

发表评论

电子邮件地址不会被公开。 必填项已用*标注