frankenphp worker 反复退出主因是初始化或首请求时触发致命错误、oom killer 终止或违反生命周期约束;需通过日志捕获、dmesg 查杀记录、内存限制调整、入口逻辑校验及环境依赖检查综合排查。

FrankenPHP Worker 启动后反复退出,基本不是配置写错,而是进程在初始化或首次请求处理阶段就触发了 Fatal Error、未捕获异常,或被系统强制终止——必须从错误日志、进程状态、启动上下文三方面交叉验证。
看错误日志是否记录了 Fatal 或 Segmentation Fault
Worker 进程崩溃前通常会留下明确线索,但默认可能不输出到终端或系统日志:
- 在 Worker 入口脚本最顶部加:
ini_set('log_errors', 'On'); ini_set('error_log', '/var/log/frankenphp-worker.log'); - 补上 shutdown 钩子捕获致命错误:
register_shutdown_function(function() { $e = error_get_last(); if ($e && in_array($e['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) { error_log("FATAL EXIT: " . $e['message'] . " in " . $e['file'] . ":" . $e['line'], 3, '/var/log/frankenphp-worker.log'); } }); - 检查日志里是否出现
Segmentation fault(常因扩展冲突或 PHP 内存破坏)、Class 'XXX' not found(自动加载失败)、Allowed memory size exhausted(入口初始化时就超限)
确认进程是否被系统 OOM killer 干掉
FrankenPHP Worker 常驻内存,若初始加载框架+缓存+OPcache 就占满内存,Linux 会静默 kill 掉它,不报 PHP 错误:
- 运行
dmesg -T | grep -i "killed process",查找类似Killed process 12345 (php) total-vm:2048000kB, anon-rss:1987654kB, file-rss:0kB的记录 - 检查
/proc/$(pgrep -f "frankenphp.*worker")/status中的VmRSS值,对比系统可用内存 - 临时降低内存压力:启动时加
--php-flags "-d memory_limit=512M",并确认opcache.enable_cli=0(CLI 模式下 OPcache 默认关,但某些发行版会开)
检查 Worker 入口是否违反 FrankenPHP 生命周期约束
Worker 脚本不是普通 PHP 文件,任何“一次性”操作放在循环里都会导致崩溃或退出:
- 确保
frankenphp_handle_request()只调用一次,且包裹全部业务逻辑;不要把它放进while(true)循环里重复执行 - 禁止在回调外调用
exit、die或抛出未捕获的Exception—— 这会让整个 Worker 线程终止 - 检查是否误用了
register_shutdown_function():它在 Worker 模式下不可靠,可能不执行,或在错误时机执行导致资源释放冲突 - 确认没有在入口处执行耗时阻塞操作(如
file_get_contents('http://...')、同步 Redis 查询),它们会卡住事件循环,触发 Caddy 超时后主动 kill 进程
验证是否因环境变量或扩展缺失导致启动失败
Worker 进程由 FrankenPHP 主进程 fork,继承的环境比 CLI 更精简,容易缺关键依赖:
- 在入口脚本开头加:
error_log("ENV: " . print_r($_ENV, true), 4); error_log("EXTS: " . print_r(get_loaded_extensions(), true), 4);,确认pdo_mysql、redis、mbstring等必需扩展已加载 - 检查
.env是否被正确读取:FrankenPHP 不自动加载.env,需显式调用Dotenv\Dotenv::createImmutable(__DIR__)->load(); - 若用 Docker,确认
/tmp可写(socket 和 OPcache 文件需要),且/dev/shm容量足够(OPcache 共享内存段依赖它)
反复退出最常被忽略的是:你以为在调试 Worker,其实 Caddy 正在后台不断拉起新实例,而旧日志被覆盖。务必先停掉所有 FrankenPHP 进程(pkill -f frankenphp),再用 frankenphp run --worker ./public/worker.php --debug 单实例前台启动,盯着终端输出——这才是真实崩溃现场。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











