跳到正文
服务器与 .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 生成器 重新生成一段干净的规则,粘贴进去,然后强制刷新再测一次。

FAQ

常见问题

为什么 WordPress 文章返回 404,首页却正常?

因为 WordPress 依赖的 URL 伪静态规则在 .htaccess 里丢失或已损坏。首页正常,是因为访问 / 会直接由根目录下的 index.php 处理;而文章 URL 在磁盘上并不是一个真实目录,需要 Apache 在内部把请求转交给 index.php。

所有页面都是 404,该怎么修?

进入 wp-admin 的「设置 → 固定链接」,什么都不改,直接点击「保存更改」。这会强制 WordPress 重新生成 .htaccess 里的伪静态规则块,大多数情况都能因此解决,包括站点迁移后遗留下来的过期规则。

WordPress 的 .htaccess 文件在哪里?

它和 wp-config.php 在同一个目录,也就是 WordPress 安装的根目录。这是一个以点开头的隐藏文件,需要在 FTP 客户端里打开「显示隐藏文件」才看得到,或者在安装路径下用 ls -la 直接列出来。

为什么 WordPress 总是覆盖我的 .htaccess 文件?

WordPress 只会重写 # BEGIN WordPress 和 # END WordPress 两个标记之间的内容,而且只在该文件对 Web 服务器可写时才会重写。标记之外的内容不会被动,所以把你自定义的指令写在 # BEGIN WordPress 那一行的上方,就不会被清掉。

重新保存固定链接之后还是 404,是怎么回事?

多半是 Apache 根本没有读取你的 .htaccess。如果虚拟主机配置是 AllowOverride None,Apache 会直接跳过这个文件,无论里面写了什么,所以你需要对 WordPress 所在目录设置 AllowOverride All,至少也要有 FileInfo。同时确认 mod_rewrite 已启用。Nginx 完全不使用 .htaccess。