frankenphp worker 退出后自动拉起是 caddy 的默认保活行为,由 php_worker 指令触发;worker 必须用 while(true) 循环维持长连接,否则脚本结束即被 caddy 替换;frankenphp_worker=1 环境变量必须正确设置,否则 worker 模式不生效。

FrankenPHP Worker 退出后自动拉起是 Caddy 的默认行为
FrankenPHP 本身不管理 Worker 生命周期,Worker 进程退出(无论正常 return 还是 die())后是否重启,完全由 Caddy 控制。只要 Caddy 的 php_worker 指令存在且配置有效,Caddy 就会把 Worker 当作“必须常驻”的子进程,一旦退出就立即 fork 新实例 —— 这不是 FrankenPHP “主动重启”,而是 Caddy 的进程保活机制。
-
php_worker指令在 Caddyfile 中启用后,Caddy 会持续监控 Worker 进程状态;即使 PHP 脚本末尾显式执行了exit(0),Caddy 仍视其为“意外终止”并拉起新 worker - 这种行为与
php_server { worker }不同:后者是同步阻塞模型,一个 worker 处理完一个请求即结束,但 Caddy 不会再启;而php_worker是异步长连接模型,Caddy 假设它应永远运行 - 如果你在 worker 脚本里写了
frankenphp_handle_request()回调但没加循环(比如漏了while (true) { ... }),回调执行完脚本自然退出,Caddy 立刻补上一个新进程
worker 脚本里没写死循环就会退出
FrankenPHP 的 php_worker 模式要求脚本持续监听请求,不是“执行一次就完”。官方示例中那个无限 while (true) 循环不是可选的装饰,而是必需的运行结构。一旦循环中断或脚本到达 EOF,进程生命周期结束,触发 Caddy 的自动拉起逻辑。
- 典型错误写法:
frankenphp_handle_request(function () { echo "hello"; });—— 执行完回调即退出,Caddy 补一个新进程 - 正确写法必须包裹在循环内:
while (true) { frankenphp_handle_request(...); },否则无法维持长连接语义 - 如果用了
break或return提前跳出循环,效果等同于脚本结束,同样触发补位
环境变量 FRANKENPHP_WORKER=1 没生效会导致行为错乱
即使 Caddyfile 写了 php_worker,若启动 FrankenPHP 时没设 FRANKENPHP_WORKER=1,整个 worker 模式根本不会激活。此时 Caddy 可能降级为普通 CGI 模式,或静默忽略 php_worker 指令,导致你看到的“反复启动”其实是不同模式下的混合表现 —— 看似重启,实为配置未对齐。
-
FRANKENPHP_WORKER=1必须作为环境变量传给frankenphp run,不能写在 Caddyfile 或 .env 里 - 用
systemctl启动时,必须在 service 文件的[Service]段加Environment=FRANKENPHP_WORKER=1 - 检查是否生效:启动后看日志是否有
Starting PHP worker pool with N workers;没有则说明 worker 模式压根没起来
别在 worker 脚本里调用 exit() 或触发 fatal error
任何让 PHP 进程非正常终止的操作,都会被 Caddy 解释为 worker 崩溃,从而强制拉起新实例。这不是 bug,是设计使然 —— Caddy 把 worker 当作不可靠组件,用“快速失败 + 快速替换”保障可用性。
- 显式
exit()、die()、未捕获的Fatal error(如 undefined function)、内存超限(Allowed memory size exhausted)都会导致进程退出 - 这类退出往往伴随日志里的
worker exited: exit status 1或类似提示,紧接着出现starting new worker - 真正需要“优雅停止”的场景(如滚动发布),应该用
frankenphp stop-workers命令,它会向所有 worker 发送 SIGTERM,让它们完成当前请求后自行退出,不触发补位
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











