宝塔面板一键部署后,Nginx 伪静态规则"幽灵般"失效的72小时
上周帮朋友搭个内容站,图省事用了宝塔的一键部署 WordPress。安装过程丝滑得像德芙,直到我点开第一篇伪静态文章——404,熟悉的数字,陌生的愤怒。
先说我怎么"自信"踩坑的。宝塔默认给的 WordPress 伪静态规则长这样:
location / {
try_files $uri $uri/ /index.php?$query_string;
}
看着没毛病对吧?我甚至截图发群里说"宝塔这次终于靠谱了"。结果文章页全炸,分类页也炸,只有首页和后台苟活。我第一反应是 Permalink 设置没保存,冲进后台重新点了三遍"保存更改",甚至怀疑是 .htaccess 文件在搞鬼——忘了这环境是 Nginx。
第一阶段:怀疑人生式排查
我干了这些事:重启 Nginx(没用)、清空浏览器缓存(没用)、换电脑测试(没用)、在服务器上 curl 直接请求(还是404)。这时候已经开始瞎猜了,是不是 PHP 版本问题?切了 7.4 到 8.1 轮着试,页面从404变成了"另一种404",很稳定。
第二阶段:日志里找鬼
终于想起来看 Nginx error.log,发现一条奇怪的记录:
open() "/www/wwwroot/xxx.com/2024/09/hello-world" failed (2: No such file or directory)
等等,它怎么在找物理路径?不是应该 rewrite 到 index.php 吗?这说明 try_files 没生效,或者……被别的规则截胡了。
我打开宝塔的"配置文件" tab,逐行扫 Nginx 主配置。然后看见了这玩意儿,藏在 WordPress 规则上方,是之前某个项目残留的:
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 30d;
add_header Cache-Control "public, immutable";
try_files $uri =404;
}
问题出在这行:宝塔一键部署时,这个静态资源缓存规则的位置**恰好**在我后来添加的 WordPress 伪静态规则**之前**。但更阴险的是,我文章路径里有日期格式 `/2024/09/xxx`,而 Nginx location 匹配优先级里,正则 location(`~*` 开头)的优先级高于普通前缀 location(`/` 开头)——当没有 `^~` 修饰符时。
不对,我文章路径也不是静态文件后缀啊?再仔细看,我脑抽给媒体库启用了"组织到年月目录",而主题有个功能是"图片懒加载占位符",会把文章链接里的某些路径片段……算了直说吧,是我之前手贱加了一条测试规则:
location ~ ^/\d{4}/\d{2}/ {
# 本来想做个归档页的特殊缓存
proxy_pass http://127.0.0.1:8080;
}
这条规则还在!而且因为正则匹配,它抢在了 WordPress 的 `location /` 之前触发了。我早忘了这茬,它像个地雷埋在那,等我一脚上去。
第三阶段:钩子不触发的次生灾害
解决 404 之后,我又发现个诡异现象:文章发布时,我绑定的"自动推送到百度"钩子没反应。检查代码,用的是 WordPress 的 `publish_post` action,函数里写了错误日志,但日志文件纹丝不动。
这次学乖了,先查钩子优先级。我的代码长这样:
add_action('publish_post', 'my_baidu_push', 10, 2);
优先级 10,默认,没毛病。但我在函数开头加了 `error_log('hook fired')`,死活不输出。最后发现是……我在主题的 `functions.php` 最底下写的这段代码,而主题有个子主题,子主题的 `functions.php` 里有一行:
remove_all_actions('publish_post');
子主题是我三个月前建的,为了改个页脚版权信息。当时顺手把父主题里一堆"用不上的钩子"全清了,包括这个我自己写的推送钩子。最绝的是,子主题激活后我从来没切回去看过,完全忘了这码事。
现在我的排查流程
1. 遇到路由/重写问题,先 `nginx -T` 看完整配置,别只盯站点配置
2. 钩子不触发,先 `grep -r "remove_action\|remove_all_actions"` 扫一遍主题和插件目录
3. 任何"一键部署"后,花两分钟确认默认规则的位置和优先级,别被"丝滑"麻痹
4. 子主题是个好东西,也是藏尸的好棺材,定期审计
朋友说请我吃饭答谢,我说算了,这72小时够我点二十顿外卖。现在他那站跑得好好的,而我养成了个怪癖:每次打开宝塔面板,先点"配置文件"而不是"网站",看完再干别的。

