
SSL 证书签发成功伪静态规则配置完成运行目录指向了 public。但是页面就是打不开。顺手拿http://开头的地址试一下它很配合地 301 跳到了https://。到这儿我以为部署完了。然后去访问接口地址——页面打不开。没有 502没有 404 页面没有 PHP 报错。浏览器上就是一片空白或者一句「无法访问此网站」。这时候最常见的反应是回去翻 Nginx 配置是不是 location 写错了伪静态规则不对server_name 没匹配上都不是。这批机器是 1Panel OpenResty PHP 容器站点跑的是 ThinkPHP 8刚做完首次部署的验收。关键在于问一句刚才那个 301 跳转是谁干的。是 Nginx在这儿就是 OpenResty。它要干成这件事得同时满足 3 条进程在监听 80 端口server_name 匹配上了这个域名跳转规则不管是return 301还是rewrite被正确执行。3 条全成立跳转才会成功。所以跳转成功这件事本身就是一份体检报告。没监听、端口没放行表现是连接被拒绝或者超时。证书有问题表现是证书错误、UNABLE_TO_VERIFY_LEAF_SIGNATURE。后端 PHP 挂了但 Nginx 正常表现是能连上、能跳转但页面空白或 5xx。第三种就是当时的情况。问题一定在跳转之后的处理环节也就是 PHP。这个判断把排查范围从整个 Web 栈直接压到了 PHP 应用省掉大量瞎猜。往下一层看入口文件。PHP 站点的入口通常是public/index.php而这个文件的第一行有效代码几乎都是同一句require__DIR__./../vendor/autoload.php;vendor/不存在这一行就让 PHP 进程直接崩。注意严重程度这不是某个函数调用失败也不是某个页面返回错误这是加载阶段的 Fatal error。区别在于框架已经跑起来、只是路由匹配不上你会看到一个 404 页面甚至是框架自带样式的错误页vendor缺失框架根本没被加载连优雅地报一个错的能力都没有。所以最后看到的是「页面打不开」而不是 404。它连 404 都渲染不出来。vendor/为什么永远不会自己出现这才是这篇真正值得记的地方。两件事叠在一起。一是.gitignore里写了/vendorgit clone下来的仓库天然不含vendor/这是 PHP 项目的通行做法依赖不进版本库。二是部署脚本的 rsync 排除清单里也写了vendor/这一条本身正确且必要否则每次更新代码都会把服务器上装好的依赖删光。两条都没错。于是结果就是这个站点目录里不会有vendor/而且永远不会自己出现。那它从哪来只能原地装。composerinstall--no-dev仓库里带了composer.lock的话这一步就是可复现的——严格按锁定版本安装不随服务器 PHP 版本浮动。所以composer.lock务必纳入版本控制。症结在于排除清单和启动必需件是同一批文件。rsync 要排除.env、vendor/、runtime/理由是它们不是代码、不该被同步覆盖。可它们又都是必须存在的东西。排除不等于不需要只是不由同步来负责。部署流程如果只写了排除什么却没写排除之后由谁生成就一定会漏而且漏得毫无察觉rsync 不回显任何异常目录列表看起来完全正常直到你去访问站点。装完依赖再访问页面有反应了。错误换了个样子。第 2 层.env也不在。它和vendor/是同一个原因.gitignore忽略了它rsync 排除清单里也有它。所以数据库配置、密钥全是空的。表现出来是能访问了但数据库连不上。第 3 层请求的地址本身可能就是错的。这层最容易被忽略因为前两层修好之后报错信息会突然变得很像业务问题。当时访问的是/api/index/ping回显四个字方法不存在。这条回显含金量很高。它证明框架已经完全跑起来了能实例化控制器、能查路由表只是路由表里没有这一条。所以它恰好出现在前两层修好之后、第 3 层修好之前把三层问题的修复时序直接打了出来。去路由文件里核对这个动作确实存在只是注册在另一个分组下实际访问 /api/index/ping 正确地址 /api/auth/ping改对地址接口回 pong。从「打不开」到「方法不存在」再到「pong」报错是一条收敛路径——前两层没修好之前第 3 层根本不会暴露。