Webman项目用GitHub Actions做CI/CD可行,但需绕开php-fpm惯性思维,改用webman stop -f与webman start控制Swoole常驻进程,并排除.rsync同步中的.env和runtime目录,避免PID丢失与配置覆盖。

Webman 项目用 GitHub Actions 做 CI/CD 是可行的,但必须绕开它默认依赖 php-fpm 管理进程的惯性思维——Webman 是常驻内存的 Swoole/Hyperf 风格框架,部署时不能靠 reload php-fpm,而要控制 webman start / webman stop 进程生命周期。
为什么直接套用 PHP 通用部署模板会失败
多数 PHP 项目的 GitHub Actions 模板(比如用 appleboy/ssh-action reload nginx + php-fpm)在 Webman 上会静默失效:服务看似“重启”了,但旧 worker 进程仍在跑,新代码根本没加载。这是因为 Webman 启动后由 Swoole 主进程托管,不走 FPM 的 fastcgi 通信链路。
常见错误现象包括:
- 代码已推送,
curl请求返回旧页面或 502 - SSH 登录服务器执行
ps aux | grep webman,发现多个webman start进程并存 - 日志里反复出现
Address already in use(端口被占),说明 stop 没真正生效
关键步骤:用 ssh-action 正确启停 Webman 进程
核心是让远程服务器上执行的命令能干净地 kill 掉旧进程、再拉起新实例。不能只写 webman start,必须加进程管理逻辑。
推荐做法:
- 在目标服务器上,把 Webman 项目部署到固定路径(如
/var/www/webman),确保webman命令全局可用(composer global require webman/console或加软链) - Workflow 中使用
appleboy/ssh-action@v0.1.4(注意不是 v0.1.0,新版支持更稳定的连接重试) - stop 步骤必须带
-f强制终止:cd /var/www/webman && webman stop -f - start 步骤建议后台运行并重定向日志:
cd /var/www/webman && nohup webman start > /var/log/webman.log 2>&1 & - 加个简单健康检查:
sleep 3 && curl -s --head http://localhost:8787 | head -n 1 | grep "200 OK"(假设监听 8787)
如何避免 rsync 同步时覆盖 .env 或 runtime 目录
Webman 的 .env 和 runtime/(含日志、缓存、PID 文件)不该随代码一起覆盖。rsync 默认全量同步会清掉 PID,导致 webman stop 找不到进程。
正确配置 shogo82148/actions-rsync@v1 的 options:
- 排除敏感目录:
--exclude=".env" --exclude="runtime/" --exclude="vendor/" - 保留远程已有文件:
--ignore-existing - 启用删除保护:
--delete-excluded不要加,否则会删掉远程的runtime/ - 务必确认
dest是项目根目录(如/var/www/webman),不是子目录
本地开发与 CI 环境的 Composer 行为差异
Webman 的 composer install 在 CI 中容易出问题,原因有两个:
-
webman-plugin类插件依赖可能触发交互式提示(如是否生成配置),CI 环境无 TTY,卡住;解决:加--no-interaction - 某些插件需读取
.env才能完成安装(如数据库迁移类),但 CI 里不应传.env;解决:用--no-scripts跳过 post-install-cmd - 最终命令应为:
composer install --no-dev --no-interaction --no-scripts --prefer-dist - 如果项目有自定义启动脚本(如
start.php),记得在 rsync 后手动chmod +x
Webman 的自动化部署难点不在“怎么传代码”,而在“怎么让新代码真正接管请求”。进程控制、环境隔离、配置留存这三处稍有疏忽,就会出现“看起来部署成功,实际没生效”的情况。尤其注意 webman stop -f 是否真杀掉了所有子进程,这是最常被跳过的验证点。


















