根本原因是php worker常驻内存、复用opcache和框架容器,不自动感知文件变化;必须通过frankenphp stop-workers或启用watch:true触发sigterm使worker优雅退出并由caddy拉起新实例,同时确保路径正确、软链已切、opcache已清。

FrankenPHP 1.2 在 worker 模式下代码不更新,根本原因是 PHP worker 进程常驻内存、复用 OPcache 和框架容器,不会自动感知文件变化。改完代码后执行 frankenphp reload 或 caddy reload 完全无效——它们只重载 Caddy 配置,不重启 worker。
要让新代码生效,必须让旧 worker 退出、由 Caddy 拉起新实例,并确保新实例加载的是新路径下的入口文件和缓存。
✅ 正确触发代码更新的两种方式
-
启用
watch: true(推荐用于开发环境)
在frankenphp.yaml中配置:php_worker: /var/www/current/public/index.php watch: true
- FrankenPHP ≥ 1.2 支持该选项,会监听
.php、.yaml、.env等变更,自动向当前 worker 发送SIGTERM - 注意:不监听
vendor/目录;Composer 更新后仍需手动清 OPcache 或重启
- FrankenPHP ≥ 1.2 支持该选项,会监听
-
手动终止 worker(生产发布标准流程)
运行命令:frankenphp stop-workers
- 向所有活跃 worker 发送
SIGTERM,worker 完成当前请求后优雅退出 - Caddy 会立即拉起新 worker(前提是
startup: 1或未设限) -
必须在 FrankenPHP 主进程所在宿主机上执行,且
FRANKENPHP_WORKER=1已设为环境变量
- 向所有活跃 worker 发送
⚠️ 容易失败的隐藏陷阱(务必检查)
入口路径必须是绝对路径
php_worker指令中不能写./public/index.php或public/index.php,否则 worker 启动失败,日志仅显示模糊的"failed to start worker"
✅ 正确写法:/var/www/current/public/index.php-
软链接切换后权限与依赖未就绪
执行ln -sf /var/www/releases/20261015-xx /var/www/current后,确认:-
public/index.php可读(ls -l /var/www/current/public/index.php) -
var/cache/可写(尤其 Symfony/Laravel 的缓存目录) - 已运行
composer install --no-dev --optimize-autoloader - 若使用自定义环境(如
APP_ENV=prod),需在 Caddyfile 中显式传入:php_worker /var/www/current/public/index.php { env APP_ENV=prod }
-
-
OPcache 未清理导致旧字节码仍在运行
即使 worker 重启,若 OPcache 缓存了旧文件哈希,仍可能加载错误逻辑
✅ 解决方法(任选其一):- 调用
opcache_reset()(需 PHP CLI 或 Web 端可访问) - 使用
frankenphp opcache-reset(若二进制支持) - 启动时加参数强制刷新:
--php-flags "-d opcache.validate_timestamps=1"
- 调用
? 不起作用的操作(别再试)
-
caddy reload或frankenphp reload→ 只重载路由/TLS/静态路径,不碰 worker - 直接覆盖代码或切软链后等待 → worker 复用旧 OPcache,大概率报
Class not found或Cannot declare class -
kill -9 $PID→ 强杀无优雅退出,Caddy 可能无法及时拉起新实例,造成短暂不可用 - 修改
.env或config/*.yaml后不重建缓存 → Symfony/Laravel 读的是编译后的var/cache/prod/,不是原始配置文件
? 发布时的标准三步顺序(缺一不可)
-
部署新代码到独立 release 目录,并完成
composer install和权限设置 -
切换软链 + 清缓存:
ln -sf /var/www/releases/20261015-xxxx /var/www/current php artisan config:clear && php artisan cache:clear # Laravel # 或 php bin/console cache:clear --env=prod # Symfony opcache_reset()
-
通知 worker 退出:
frankenphp stop-workers
此刻新请求将由加载了新代码的新 worker 处理。
不复杂但容易忽略。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











