frankenphp命令找不到是因二进制未下载或无执行权限;须先运行php artisan octane:install --server=frankenphp,再检查vendor/bin/frankenphp是否存在且可执行,CI/CD中需加校验。

frankenphp 命令找不到:二进制没下载或权限不对
执行 frankenphp -v 报 command not found,基本是二进制根本没落盘,或者下载后没给执行权限。
常见于 Laravel Octane 场景:只运行了 composer require laravel/octane,却漏掉关键一步——php artisan octane:install --server=frankenphp。这一步才会触发自动下载 vendor/bin/frankenphp 并生成 vendor/bin/frankenphp-worker.php。
- 手动检查是否存在:
ls -l vendor/bin/frankenphp,若无输出,说明没下载成功 - 若存在但不可执行,运行:
chmod +x vendor/bin/frankenphp - CI/CD 构建中常因网络或超时跳过下载,建议在构建脚本里加校验:
test -x vendor/bin/frankenphp || (echo "frankenphp binary missing"; exit 1)
Linux/macOS 本地安装后无法启动:路径、权限与依赖混淆
官方二进制是静态链接的(尤其 Linux x86_64 版),理论上不依赖系统 PHP 或额外库。但很多人误以为要先装系统 php8.2-franken 包,结果反而冲突。
正确做法是直接下载独立二进制,扔进 $PATH 或项目目录下运行,别混用 APT 安装和二进制安装。
立即学习“PHP免费学习笔记(深入)”;
- 从 https://www.php.cn/link/e528fff5c6807c9f797e110d49bb5154 下载对应平台的
frankenphp-linux-x86_64(或 macOS 版) - 赋予执行权限:
chmod +x frankenphp-linux-x86_64 - 重命名为
frankenphp并移入/usr/local/bin/,或直接在项目根目录运行:./frankenphp run --config Caddyfile - Windows 用户注意:原生 Windows 不支持,必须用 WSL2;不要尝试在 Git Bash 或 Cygwin 下硬跑
Caddyfile 配置写错导致 502 或空白页
FrankenPHP 启动后访问返回 502 或完全空白,90% 是 Caddyfile 里 php_server 指令路径没对上,或 root 指向错误位置。
Laravel 项目必须确保 root 指向 public/ 目录,且 php_server 的 try_files 能 fallback 到 index.php。
- 最小可用配置示例:
localhost {
root * public/
php_server {
try_files {path} /index.php
}
encode zstd br gzip
}-
try_files {path} /index.php中的/index.php是相对于root的路径,不是文件系统绝对路径 - 如果用
php_server { }但没写try_files,静态资源能访问,PHP 请求会 404 - 别把
php_server和reverse_proxy混用——FrankenPHP 不需要反代自己
Octane worker 模式下请求异常:$_SERVER 冻结与环境变量陷阱
开启 php artisan octane:start --server=frankenphp 后,发现路由错乱、HTTPS 判断失效、请求参数丢失,大概率是代码里还直接读 $_SERVER。
worker 模式下 PHP 进程常驻,$_SERVER 在首次请求后就固化为快照,后续请求不会刷新。这是最隐蔽也最致命的坑。
- 必须替换所有
$_SERVER['REQUEST_URI']→request()->fullUrl() -
$_SERVER['REQUEST_METHOD']→request()->method() -
$_SERVER['HTTPS'] === 'on'→request()->secure() - 避免在服务提供者
register()或bootstrap/app.php中基于$_SERVER做逻辑分支(比如按 Host 加载不同配置) - 环境变量如
APP_ENV必须在启动前注入,不能靠.env文件在每次请求里重新读取(worker 不 reload)
worker 模式真正的复杂点不在启动,而在“请求上下文是否干净”——框架层能帮你屏蔽一部分,但自定义中间件、全局函数、早期 bootstrap 里的 $_SERVER 依赖,全得手动扫一遍。漏一个,就可能在线上静默出错。



















