跳到正文
服务器与 .htaccess

WordPress 文章返回 404,但首页正常打开

如果首页能正常加载,但每一篇文章和页面都返回 404,那说明 WordPress 依赖的 URL 伪静态规则在你的服务器上丢失或已损坏

发布于

如果首页能正常加载,但每一篇文章和页面都返回 404,那说明 WordPress 依赖的 URL 伪静态规则在你的 .htaccess 文件里丢失或已损坏。最快的解决办法:进入 wp-admin 的 设置 → 固定链接,什么都不改,直接点 保存更改。这会强制 WordPress 重新生成那段伪静态规则。如果 404 依然存在,那要么是 Web 服务器无权写入你的 .htaccess,要么是 Apache 被配置成忽略它,要么是你用的是 Nginx(Nginx 根本不使用 .htaccess)。

为什么首页正常,文章却打不开

首页正常,是因为对 / 的请求会直接由网站根目录下的 index.php 处理,不需要任何重写。

而对 /2026/my-post/ 的请求就不一样了。这个路径在磁盘上并不是一个真实存在的文件夹。要让 WordPress 处理它,Apache 必须在内部把请求转交给 index.php,然后 WordPress 读取 REQUEST_URI,将其与数据库里 rewrite_rules 选项中保存的伪静态规则进行匹配,解析出查询变量(WP::parse_request()),再加载对应的文章。

从 Apache 转交给 index.php 的这一步,正是容易出问题的地方。它完全依赖于 .htaccess 中的这一段:

# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress

那两行 RewriteCond 的意思是:如果请求的路径既不是真实存在的文件(!-f),也不是真实存在的目录(!-d),就把它交给 index.php。删掉这一段,Apache 就会去找一个字面上叫 /2026/my-post/ 的目录,找不到,于是返回它自己的 404 —— 在 WordPress 看到这个请求之前就已经拦下了。

为什么保存固定链接时 WordPress 会覆盖 .htaccess

这一点大多数教程都略过了。当你在固定链接设置页点保存时,WordPress 会调用 flush_rewrite_rules()。在 .htaccess 可写的 Apache 环境下,这会触发 save_mod_rewrite_rules(),它通过 WP_Rewrite::mod_rewrite_rules() 重新生成上面那段规则,并用 insert_with_markers() 写回文件。

insert_with_markers() 只会改动 # BEGIN WordPress# END WordPress 之间的内容。这两个标记之外的一切都原封不动,标记之内的一切都会被丢弃并重写。较新版本的 WordPress 甚至会把这句警告直接写进文件里:

Any changes to the directives between these markers will be overwritten.

所以「WordPress 覆盖了我的 .htaccess」这句话没错,但范围很有限:它只重写自己标记的那一段,而且只在文件可写时才会这样。如果文件 不可写,保存操作对磁盘不会有任何改动,静默失败。WordPress 会在固定链接设置页上显示一条黄色提示,让你手动把规则粘贴进去;如果你没注意到那条提示,那段伪静态规则就一直缺失,每篇文章也就一直返回 404。

按顺序修复

1. 重新保存固定链接。 设置 → 固定链接 → 保存更改。不用做任何修改。这会重新执行刷新并重写那段规则。它能解决大多数情况,包括迁移之后规则失效的问题。

2. 检查 .htaccess 是否存在且可写。 它和 wp-config.php 在同一个文件夹里。它是隐藏文件(以点开头),所以要在 FTP 客户端里开启「显示隐藏文件」,或者用:

ls -la /path/to/wordpress/.htaccess

如果文件不存在,就新建一个并粘入正确的规则段。如果你的 WordPress 装在子目录里,RewriteBase 和最后那条重写目标必须与该路径一致 —— 弄错这个,是手动粘贴的规则仍然报 404 最常见的原因。我们的 .htaccess 生成器 会针对你的安装路径生成完全正确的规则段,省得你去猜。

3. 确认 Apache 被允许读取 .htaccess 如果虚拟主机配置了 AllowOverride None,Apache 会完全忽略这个文件,不管里面写了什么。你需要在 WordPress 所在目录上设置 AllowOverride All(至少也要 FileInfo)。这项配置在服务器配置里,不在 .htaccess 里,所以需要服务器访问权限:

<Directory /var/www/html>
    AllowOverride All
</Directory>

4. 确认 mod_rewrite 已启用。 在 Debian/Ubuntu 上:

sudo a2enmod rewrite
sudo systemctl restart apache2

5. 在 Nginx 上,根本没有 .htaccess 重写规则要写在 server 块里:

location / {
    try_files $uri $uri/ /index.php?$args;
}

快速诊断:这是谁返回的 404?

看一眼这个 404 页面。如果是没有样式的 Apache 或主机错误页,说明 Apache 根本没把请求交给 WordPress —— 这是 .htaccess 或服务器配置的问题(第 2–4 步)。如果是 你主题自带的 带样式 404 页,说明 WordPress 收到了请求但匹配不上 —— 数据库里的规则已经失效,重新保存固定链接(第 1 步)就是解决办法。仅凭这一个区分,就能帮大多数人省下一个小时的瞎猜。

不要做的事

不要一上来就停用所有插件。 纯粹的「文章 404、首页正常」这种症状是伪静态问题,不是插件冲突。停用插件是论坛上的条件反射式回答,但它几乎从来碰不到这个问题的根子。

不要给你的 .htaccesschmod 777 WordPress 需要的是让 Web 服务器用户 能写入这个文件,这和「所有人可写」不是一回事。644 加上正确的属主就足够安全;777 是一个安全漏洞,而且照样修不好路由。

不要把自定义重写规则粘到 # BEGIN WordPress / # END WordPress 标记之间。 下次任何人保存固定链接时,它们都会被抹掉。自定义指令要放在 # BEGIN WordPress 那一行 上方

不要重装 WordPress。 核心文件没问题。这只是缺了一段文本,不是安装损坏。

不要怪你的主题。 固定链接路由属于 WordPress 核心。主题既不会导致这个问题,也无法解决它。

还是搞不定?

如果你已经重新保存了固定链接,确认那段规则存在且文件可写,也设置了 AllowOverride All,那剩下的嫌疑对象就是某个安全插件,或者某条主机层面的规则在背后偷偷重新生成或锁定了 .htaccess。在保存固定链接之后立刻查看文件的修改时间 —— 如果时间没变,说明有东西在阻止写入。用 .htaccess 生成器 重新生成一段干净的规则,粘贴进去,然后强制刷新再测一次。