Z-Blog 伪静态开启后文章页 404:nginx 与 Apache 两种配法逐行对比

· zblog · 阅读 13
摘要

后台把伪静态打开,首页正常,一点文章就 404。这是 Z-Blog 换服务器后最容易被卡住的一步——规则文件存在,但服务器没读它,或者读了但正则对不上。 下面把 nginx 和 Apache 两套配法拆开讲,每一行说明它在做什么,出问题时能

后台把伪静态打开,首页正常,一点文章就 404。这是 Z-Blog 换服务器后最容易被卡住的一步——规则文件存在,但服务器没读它,或者读了但正则对不上。

下面把 nginx 和 Apache 两套配法拆开讲,每一行说明它在做什么,出问题时能对得上。

先确认:Z-Blog 的伪静态是「程序生成规则,服务器执行」

Z-Blog 本身不做 URL 重写,它只负责两件事:

  1. 把规则写进数据库配置(ZC_POST_REGEX、ZC_CATE_REGEX 等)
  2. 在后台「静态管理中心(STACentre)」里提供一份 nginx / Apache 可用的规则文本,让你复制走

真正干活的是 nginx 的 rewrite 或 Apache 的 .htaccess。规则没粘到服务器上,伪静态就不会生效。这是 404 的第一大原因。

nginx 配法逐行说明

在站点的 server { } 块里,location / { } 之前加上这段:

if (-f $request_filename) {
    break;
}

rewrite ^/([^/]+)\.html$ /index.php?p=$1 last;
rewrite ^/page_([0-9]+)\.html$ /index.php?page=$1 last;
rewrite ^/([^/]+)/$ /index.php?cate=$1 last;

逐行看:

  • if (-f $request_filename) { break; }:如果请求的文件真实存在(比如 /favicon.ico、/zb_system/style/a.css),直接返回,不做重写。少了这句,静态资源会被改写进 index.php,导致全站样式丢失。这句不能少。
  • rewrite ^/([^/]+)\.html$ ... last;:把 /post/31.html 里的 post/31 捕获成 $1,交给 index.php。这里的正则必须和后台 STACentre 里显示的「文章规则」对得上。
  • last:重写完成后重新走一遍 location 匹配。用 break 会停在同一 location,容易出问题,建议一律用 last。

Apache 配法逐行说明

在站点根目录建 .htaccess,内容:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /

RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)\.html$ index.php?p=$1 [L,QSA]
RewriteRule ^page_([0-9]+)\.html$ index.php?page=$1 [L,QSA]
RewriteRule ^([^/]+)/$ index.php?cate=$1 [L,QSA]
</IfModule>

逐行看:

  • RewriteCond %{REQUEST_FILENAME} !-f:请求的文件不存在才重写。等价于 nginx 那句 if (-f ...) break。
  • RewriteCond %{REQUEST_FILENAME} !-d:请求的目录不存在才重写。少这句,/zb_users/ 这类真实目录会被吃掉。
  • [L,QSA]:L 表示这是最后一条规则,QSA 表示保留原 URL 的查询串。

404 的五种具体成因与对应解法

成因一:规则根本没粘(最常见,占一半以上)

后台开了伪静态,但服务器上什么都没有。检查方法:

nginx:在站点配置里搜 rewrite
Apache:ls -la 站点根目录,看有没有 .htaccess

没有就是没粘。解决办法:后台「应用中心 → STACentre → 静态管理中心」,页面下方会给出当前配置对应的规则文本,整段复制到服务器。

成因二:nginx 没 reload

改完配置不 reload 等于没改:

nginx -t && nginx -s reload

nginx -t 先测语法,通过再 reload。语法错的话 reload 会失败,配置还是老的。

成因三:location / { } 里有 try_files 抢在前头

宝塔默认站点配置里常见:

location / {
    try_files $uri $uri/ =404;
}

这段会把 /post/31.html 当静态文件找,找不到直接 404,轮不到后面的 rewrite 执行。

解决办法:把 rewrite 规则放到 location / { } 的前面,或者把 try_files 那行改成:

try_files $uri $uri/ /index.php?$args;

成因四:PHP 版本与 PATH_INFO 问题

如果 index.php 能收不到 $1,文章页会变成「首页内容 + 404 状态码」。检查 fastcgi_param 里有没有:

fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_split_path_info ^(.+\.php)(/.+)$;

PHP 7.0 以后 cgi.fix_pathinfo 默认是 1,一般不用改;老版本 PHP 需要设成 0。

成因五:规则与后台配置对不上

后台 STACentre 里如果选的是「/post/31.html」这种带目录的形式,nginx 规则必须写成:

rewrite ^/post/([0-9]+)\.html$ /index.php?p=$1 last;

写成 ^([^/]+)\.html$ 就匹配不到带 post/ 前缀的 URL。**后台的 URL 格式和服务器正则必须一致**,这是最容易忽略的一点。

验证方法:看 HTTP 状态码,不看页面内容

很多人以为「页面能打开」就是成功,其实可能是 200 状态码返回了首页内容。用命令行确认:

curl -I http://你的域名/post/31.html

正确的结果应该是:

  • HTTP/1.1 200 OK 或 301/302 跳转
  • 不能是 404
  • 页面内容要和文章标题对得上(用 curl 不带 -I 看几行 HTML)

常见问题

Q1:开启伪静态后首页也 404 了,怎么办?

说明 if (-f $request_filename) 或 try_files 那层出了问题。先把伪静态规则整段注释掉,确认首页恢复,再一段一段加回来。

Q2:后台能进,前台所有页面都 404?

location / { } 里通常有 try_files $uri $uri/ =404。后台走的是 /zb_system/admin/ 这种真实路径,能找到文件;前台是虚拟路径,找不到就 404。把 =404 改成 /index.php?$args 立解。

Q3:Apache 下 .htaccess 写了但不生效?

查 Apache 主配置 httpd.conf 里站点目录的 AllowOverride 值。必须是 AllowOverride All,如果是 None,.htaccess 会被完全忽略。

Q4:伪静态开了,但后台设置里显示的还是 index.php??

那是 ZC_STATIC_MODE 没设成 REWRITE。在 zb_users/c_option.php 里确认:

'ZC_STATIC_MODE' => 'REWRITE',

Q5:开了伪静态,sitemap.xml 和 robots.txt 还能访问吗?

能,前提是规则里保留了 if (-f $request_filename) break; 或 !-f 条件。这两个文件是物理存在的静态文件,只要不被重写就能正常返回。

Q6:改用 PHP 8 之后原来的规则还有效吗?

规则作用在 nginx/Apache 层,和 PHP 版本无关。但 PHP 8 下 try_files 行为和之前一致,无需改规则。真正需要改的是 Z-Blog 的 PATH_INFO 相关判断,通常不用动。

"}