frankenphp是单体web服务器二进制,前台运行时按ctrl+c即可停止;systemd托管需配置killsignal=sigterm和guessmainpid=no;不支持supervisor,进程僵死时需查dmesg或重启宿主机。

FrankenPHP 本身不是传统意义上的守护进程管理器,它是一个单体 Web 服务器二进制,内置 PHP 运行时,启动后即作为主服务进程运行。它没有 start/stop/restart 脚本或内置 daemon 控制接口——所以“启动后无法停止”,通常不是 FrankenPHP 自身卡死,而是你混淆了它的运行模式,或被系统级托管工具(如 systemd、supervisor)干扰。
下面分几种典型场景说明原因和应对方式:
你直接执行 ./frankenphp 启动,但关不掉
这是最常见误解:`./frankenphp` 默认以前台模式运行(类似 `php -S`),它会阻塞终端,按 Ctrl+C 即可退出。 如果按了 Ctrl+C 没反应,大概率是: - 终端输入焦点不在前台(比如你用了 tmux/screen 但没切回对应 pane) - FrankenPHP 正在处理长连接或 Mercure 推送,暂时未响应中断信号 - 你误加了 `-d` 或 `--daemon` 参数(FrankenPHP **不支持** `-d`;该参数属于 Workerman 或自定义脚本)✅ 正确做法:
- 确保用
./frankenphp server(默认前台)启动 - 直接按 Ctrl+C 停止
- 不要重定向
> /dev/null 2>&1 &后就丢手不管——这样会导致无法交互终止,且日志丢失
你用 systemd 托管 FrankenPHP,systemctl stop 不生效
systemd 需要明确知道进程主 PID 和停止方式。FrankenPHP 默认不生成 PID 文件,也不响应 `SIGTERM` 做优雅退出(v0.12+ 开始支持,但需显式启用)。✅ 必须配置 systemd service 文件时注意:
[Service] Type=simple ExecStart=/path/to/frankenphp server --config /path/to/Caddyfile Restart=on-failure KillSignal=SIGTERM TimeoutStopSec=30 # 关键:告诉 systemd 主进程就是启动的这个 PID,不 fork 子进程 GuessMainPID=no
- 若省略
GuessMainPID=no,systemd 可能追踪错进程(尤其 Caddy 模块有子 goroutine) -
TimeoutStopSec=30防止强制 kill,给 HTTP 连接和 Mercure 清理留时间 - 启动后检查:
systemctl status frankenphp→ 看 Active line 是否为active (running),Main PID 是否匹配ps aux | grep frankenphp
你用 Supervisor 管理 FrankenPHP,supervisorctl stop 失败
Supervisor 不适合托管 FrankenPHP。原因很直接: - Supervisor 设计用于管理**短命或可重启的 worker 进程**(如 queue:work) - FrankenPHP 是一个**长期持有监听端口、TLS 上下文、HTTP/3 流状态的单进程服务**,它自己负责连接生命周期 - Supervisor 强发 `SIGTERM` 后若 FrankenPHP 未注册信号处理器,就会被立即 `SIGKILL`,造成连接中断、证书缓存失效等问题❌ 不推荐:
[program:frankenphp] command=/path/to/frankenphp server autostart=true autorestart=true ; ← 这会导致频繁闪断,破坏 HTTP/3 连接复用
✅ 替代方案:
- 用 systemd 原生托管(更稳定、信号语义清晰)
- 或直接前台运行 +
nohup ./frankenphp server > /var/log/frankenphp.log 2>&1 &,用pkill -f "frankenphp server"手动终止(仅限开发/测试)
进程僵死,kill -9 也杀不掉
极少数情况(如内核级挂起、cgroup 冻结、SELinux 策略拦截),进程显示 `D`(uninterruptible sleep)状态:- 运行
ps aux | grep frankenphp,看 STAT 列是否为D - 检查
dmesg -T | tail -20是否有SELinux: denied或cgroup: frozen - 查看
/proc/<pid>/stack</pid>确认卡在哪个内核函数(需 root)
这种情况不是 FrankenPHP 的 bug,而是底层环境异常。临时解法:
- 重启宿主机(最可靠)
- 若在容器中,尝试
docker kill --signal=SIGQUIT <container></container>触发 Go runtime panic 日志
FrankenPHP 的设计目标是“开箱即用、单进程可控”,它不需要额外守护层。只要用对启动方式、配好 systemd、避开 Supervisor 误用,停止操作就和 nginx stop 一样直接可靠。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











