FrankenPHP服务停止后端口仍被占用,需先以管理员身份运行netstat -ano | findstr :端口号查PID,再用tasklist | findstr PID确认进程名;若为frankenphp.exe或php.exe(含bin/console等)可taskkill /F /PID终止,若PID=4则禁用W3SVC等系统服务,或改配置使用空闲端口如--addr :8080,同时清理/tmp/frankenphp.sock等残留socket文件。

FrankenPHP 服务停止后端口仍被占用,说明有残留进程没退出干净,或系统级服务(如 HTTP.sys)持续监听——它不是 FrankenPHP 没停掉,而是别的东西抢了位置。
查 PID:先确认谁真正在用那个端口
必须以管理员身份运行命令行,否则看不到 system 级进程:
-
netstat -ano | findstr :8000(把8000换成你实际被占的端口号) - 看输出最后一列数字,就是 PID;若没输出,试试
:80或:443 - 再执行
tasklist | findstr "1234"(1234换成上一步查到的 PID),看进程名
常见结果:frankenphp.exe 是旧实例没退;php.exe 可能是 php -S 或 Symfony messenger:consume;System + PID=4 就是 Windows 的 HTTP.sys 驱动,不能杀。
别乱 kill:区分可终止和不可终止的进程
安全操作只针对明确识别出的残留:
立即学习“PHP免费学习笔记(深入)”;
- 如果是
frankenphp.exe或php.exe(且命令行含bin/console、messenger:consume、web-server:run)→taskkill /F /PID 1234 - 如果是
Skype.exe、Zoom.exe、com.docker.backend.exe→ 关掉对应软件即可 - 如果是
System且 PID=4 → 不要taskkill,否则可能蓝屏或断网;改走禁用 W3SVC 等服务
特别注意:pkill php 或 taskkill /F /IM php.exe 是危险操作,会干掉正在运行的新 FrankenPHP 实例。
改配置比清进程更可靠:永久避开端口冲突
与其每次手动查杀,不如让 FrankenPHP 启动时就用空闲端口:
- 命令行启动:加
--addr :8080,例如frankenphp serve --addr :8080 - TOML 配置(
frankenphp.toml):改[server] address = "127.0.0.1:8080" - Docker 启动:确保
docker run -p 8080:8080,且配置里address也同步改成:8080
改完别忘了检查代码里硬写的 URL(比如 http://localhost → http://localhost:8080),否则前端请求仍发往旧端口。
Unix socket 文件残留也会导致“端口被占”错觉
FrankenPHP 默认用 Unix socket(如 /tmp/frankenphp.sock)与 Caddy 通信。若上次异常退出没删它,新实例会报 Address already in use,看起来像端口冲突,实则是 socket 文件没清理:
- Linux/macOS:运行
ls -l /tmp/frankenphp.sock确认存在,然后rm -f /tmp/frankenphp.sock - Windows WSL:同上;纯 Windows 不用管这个,但要注意命名管道或临时文件残留
这个点最容易被忽略——错误日志里不提 socket,只说 bind 失败,人就本能去查端口,绕一大圈才发现是 sock 文件卡住了。



















