本文约 5,363 字,预计阅读 14 分钟。文中命令与配置均经过实测,可直接参考执行。
引言:只要一个博客频道
常见需求:
- 官网是用 Vue/React 做的,只想加一个
/blog用 WordPress; - 主站是静态页或别的 CMS,wordpress 只做内容模块;
- 想先在
/blog测试,将来再移到根目录。
这时候 WordPress 不能装在网站根目录,必须装到子目录。看起来简单,但固定链接、资源路径、后台跳转等环节都有坑。
原理分析:两种”子目录”含义完全不同
这是最容易搞混的地方,必须先分清:
类型 A:WordPress 文件在子目录,但站点在根目录访问
文件位置:/var/www/mimangfei/wordpress/
访问地址:https://mimangfei.com/
即”文件放子目录,URL 在根”。WordPress 官方称之为 “Giving WordPress Its Own Directory”。
需要:
- 「设置 – 常规」里 WordPress 地址填
https://mimangfei.com/wordpress,站点地址填https://mimangfei.com; - 根目录放一个
index.php转发到子目录。
类型 B:WordPress 文件和访问都在子目录
文件位置:/var/www/mimangfei/blog/
访问地址:https://mimangfei.com/blog/
即”文件在子目录,URL 也在子目录”。这是本文重点讲的场景。
两种配置的差别很大,混用会导致 404 或重定向异常。
保姆级实操
类型 B:完整安装到 /blog
第一步:放置文件
cd /var/www/mimangfei
# 下载并解压
wget https://cn.wordpress.org/latest-zh_CN.tar.gz
tar xzf latest-zh_CN.tar.gz
mv wordpress blog
现在路径是 /var/www/mimangfei/blog/,站点根是 /var/www/mimangfei/(可能是别的系统)。
第二步:Nginx 配置
server {
listen 443 ssl http2;
server_name mimangfei.com www.mimangfei.com;
root /var/www/mimangfei; # 主站根目录
# 主站(假设是静态或其他程序)
location / {
try_files $uri $uri/ /index.html;
}
# WordPress 子目录
location ^~ /blog {
root /var/www/mimangfei;
index index.php;
try_files $uri $uri/ /blog/index.php?$args;
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
# 后台不缓存
location ~ ^/blog/wp-admin/ {
try_files $uri $uri/ /blog/index.php?$args;
}
}
}
关键点:
try_files的兜底是/blog/index.php?$args,必须带/blog/前缀,否则会转发到主站的index.php;root仍然是站点根(/var/www/mimangfei),因为 URL/blog/xxx映射到文件/var/www/mimangfei/blog/xxx;SCRIPT_FILENAME用$document_root$fastcgi_script_name,$document_root是/var/www/mimangfei,$fastcgi_script_name是/blog/index.php,拼起来正确。
第三步:安装 WordPress
访问 https://mimangfei.com/blog/wp-admin/install.php,正常走安装流程。
安装后「设置 – 常规」:
WordPress 地址(URL):https://mimangfei.com/blog
站点地址(URL): https://mimangfei.com/blog
两个都带 /blog,这是类型 B 的正确配置。
第四步:固定链接
「设置 – 固定链接」选”文章名”,生成的 URL 是:
https://mimangfei.com/blog/文章别名/
.htaccess(Apache)会自动生成在 /blog/ 目录下:
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /blog/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /blog/index.php [L]
</IfModule>
# END WordPress
注意 RewriteBase /blog/——如果这行不对,固定链接全 404。
类型 A:文件在子目录,站点在根目录
第一步:安装到子目录
按类型 B 的方式先装好,站点地址暂时是 https://mimangfei.com/wordpress。
第二步:改站点地址
后台「设置 – 常规」:
WordPress 地址(URL):https://mimangfei.com/wordpress ← 不变
站点地址(URL): https://mimangfei.com ← 改成根目录
第三步:复制 index.php 和 .htaccess 到根目录
cp /var/www/mimangfei/wordpress/index.php /var/www/mimangfei/index.php
编辑根目录的 index.php,改这一行:
// 原:
require( __DIR__ . '/wp-blog-header.php' );
// 改为:
require( __DIR__ . '/wordpress/wp-blog-header.php' );
Apache 再把 .htaccess 也复制到根目录,内容不用改(RewriteBase 保持 /)。
第四步:完成
现在访问 https://mimangfei.com/ 就是 WordPress 首页,后台在 https://mimangfei.com/wordpress/wp-admin/。
Nginx 配置(类型 A):
server {
root /var/www/mimangfei;
index index.php;
location / {
try_files $uri $uri/ /index.php?$args;
}
# 后台路径要能访问到子目录
location /wordpress/ {
try_files $uri $uri/ /wordpress/index.php?$args;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass unix:/run/php/php8.2-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
}
类型 C:从子目录迁到根目录
如果先用类型 B 跑了一阵,想移到根目录:
# 1. 备份
wp db export /backup/before-move.sql --path=/var/www/mimangfei/blog --allow-root
# 2. 后台改站点地址(或命令行)
wp option update siteurl 'https://mimangfei.com' --path=/var/www/mimangfei/blog --allow-root
wp option update home 'https://mimangfei.com' --path=/var/www/mimangfei/blog --allow-root
# 3. 移动文件
mv /var/www/mimangfei/blog/* /var/www/mimangfei/
# 4. 替换数据库里的旧路径
wp search-replace 'https://mimangfei.com/blog' 'https://mimangfei.com' \
--path=/var/www/mimangfei --skip-columns=guid --allow-root
# 5. 改 Nginx 配置(去掉 /blog 的 location)
# 6. 旧地址 301 到新地址
Nginx 加 301:
location ^~ /blog/ {
rewrite ^/blog/(.*)$ https://mimangfei.com/$1 permanent;
}
常见踩坑
- 固定链接 404:
try_files兜底写成了/index.php?$args(少了/blog/),请求被转发到主站的 index.php。 RewriteBase不对:Apache 下自动生成的是/blog/,如果手动改过就 404。- 资源 404(CSS/JS 加载不了):站点地址没加
/blog,WordPress 生成的资源 URL 是/wp-content/...而不是/blog/wp-content/...。检查wp option get siteurl。 - 案例:某站在根目录下已经有一个其他系统的
index.php,WordPress 装在/blog后,访问/blog/文章名/一直跳到主站首页。原因是根index.php里的程序把所有未匹配路由都渲染成自己的首页。解决:把子目录的 location 写在根 location 之前,或用^~前缀提高优先级(上面配置已用^~)。 - 后台登录后跳到根目录:
siteurl和home配置不一致导致。两个都要带/blog(类型 B)。 - sitemap 路径:子目录安装的 sitemap 在
/blog/wp-sitemap.xml(WP 5.5+)或插件生成的路径。提交给搜索引擎时路径要带/blog。 - robots.txt:WordPress 动态生成的 robots.txt 只作用于
/blog/下的路径,对主站无效。主站需要自己的 robots.txt。 - cookie 路径:子目录安装的 WordPress cookie 作用域默认是
/(WordPress 会设成站点路径),一般没问题;但如果主站也用了同名 cookie 可能冲突。 - CDN 缓存规则:记得给
/blog/路径单独配规则,且不要缓存/blog/wp-admin/。参考WordPress CDN 回源配置与缓存规则。
总结
子目录安装要先分清两种类型:文件在子目录、站点在根(类型 A,需复制 index.php 到根)和文件与站点都在子目录(类型 B,最常见)。Nginx 配置的关键是 try_files 兜底路径要带子目录前缀,且用 ^~ 让子目录 location 优先于根 location。WordPress 侧的 siteurl 和 home 必须与访问地址完全一致。迁移时注意用 wp search-replace 替换数据库里的旧路径,并给旧 URL 加 301(参考多域名与规范域名处理)。如果将来要独立成站,流程和换服务器 DNS 切换里的迁移思路一致。
