diff --git a/docs/deploy-hjf.md b/docs/deploy-hjf.md new file mode 100644 index 00000000..a3cfdcf2 --- /dev/null +++ b/docs/deploy-hjf.md @@ -0,0 +1,342 @@ +# HJF项目代码更新发布部署文档 + +本文档用于在黄精粉线上环境已经完成初始化部署后,进行代码修改后的更新发布。该环境不是首次部署场景,服务器目录、Nginx、PHP、Swoole 和宝塔进程守护均已配置并验证正常;发布流程只处理代码同步、管理后台构建产物更新、缓存清理和 Swoole 进程重启。 + +## 1. 部署信息 + +| 项目 | 值 | +| --- | --- | +| 服务器 | `182.92.142.158` | +| SSH 用户 | `root` | +| SSH 密码 | 使用 CI/CD 密钥变量保存,例如 `DEPLOY_SSH_PASSWORD` | +| 远程部署目录 | `/www/wwwroot/hjf.suzhouyuqi.com` | +| 绑定域名 | `hjf.fsgx.cn` | +| 管理后台 | `https://hjf.fsgx.cn/admin` | +| 后端入口目录 | `/www/wwwroot/hjf.suzhouyuqi.com/public` | +| 管理后台静态目录 | `/www/wwwroot/hjf.suzhouyuqi.com/public/admin` | +| 面板环境 | 宝塔面板 | +| Nginx 状态 | 已配置并正常运行 | +| PHP / Swoole 状态 | 已配置并正常运行 | +| Swoole 管理方式 | 宝塔进程守护 | + +不要把 SSH 密码写入 Git 仓库。自动化部署建议使用 SSH key;如果必须用密码,放在 CI/CD Secret 中,并通过 `sshpass -p "$DEPLOY_SSH_PASSWORD"` 注入。 + +## 2. 发布边界 + +本流程是更新部署,不包含以下首次部署事项: + +- 不初始化服务器目录。 +- 不安装 Nginx、PHP、Composer、Node.js、Swoole 扩展。 +- 不创建站点、不重新绑定域名。 +- 不重新配置 SSL。 +- 不重建数据库。 +- 不覆盖线上 `.env`。 +- 不修改宝塔站点和反向代理配置。 + +每次发布只做: + +- 拉取指定 Git 分支代码。 +- 安装 / 校验 PHP 依赖。 +- 构建管理后台 `view/admin`。 +- 同步后端代码到 `/www/wwwroot/hjf.suzhouyuqi.com`。 +- 同步管理后台静态产物到 `public/admin`。 +- 清理 ThinkPHP 缓存。 +- 通过宝塔进程守护重启 Swoole 服务。 + +## 3. 本地准备 + +在项目根目录执行: + +```bash +cd /path/to/huangjingfen +git fetch origin +git checkout fsgx-bypass-auth +git pull --ff-only origin fsgx-bypass-auth +``` + +确认 PHP 依赖存在: + +```bash +cd pro_v3.5.1 +composer install --no-dev --prefer-dist --optimize-autoloader +``` + +构建管理后台: + +```bash +cd pro_v3.5.1/view/admin +npm install +npm run build +``` + +构建产物路径: + +```text +pro_v3.5.1/view/admin/dist/ +``` + +## 4. 推荐自动化变量 + +CI/CD 中建议配置: + +```bash +DEPLOY_HOST=182.92.142.158 +DEPLOY_USER=root +DEPLOY_PATH=/www/wwwroot/hjf.suzhouyuqi.com +DEPLOY_DOMAIN=hjf.fsgx.cn +DEPLOY_SSH_PASSWORD=****** +``` + +如果使用 SSH key,则不需要 `DEPLOY_SSH_PASSWORD`。 + +## 5. 服务器备份 + +虽然不是首次部署,但每次更新发布前仍建议备份当前线上目录: + +```bash +ssh ${DEPLOY_USER}@${DEPLOY_HOST} "\ + mkdir -p /www/backup && \ + tar -czf /www/backup/hjf_fsgx_$(date +%Y%m%d_%H%M%S).tar.gz \ + -C /www/wwwroot hjf.suzhouyuqi.com" +``` + +使用密码自动化时: + +```bash +sshpass -p "$DEPLOY_SSH_PASSWORD" ssh -o StrictHostKeyChecking=no ${DEPLOY_USER}@${DEPLOY_HOST} "\ + mkdir -p /www/backup && \ + tar -czf /www/backup/hjf_fsgx_$(date +%Y%m%d_%H%M%S).tar.gz \ + -C /www/wwwroot hjf.suzhouyuqi.com" +``` + +## 6. 上传后端代码 + +从仓库根目录执行: + +```bash +rsync -avz --delete \ + --exclude='.git' \ + --exclude='.DS_Store' \ + --exclude='.env' \ + --exclude='.env-*' \ + --exclude='runtime/cache' \ + --exclude='runtime/log' \ + --exclude='runtime/temp' \ + --exclude='public/uploads' \ + --exclude='view/admin/node_modules' \ + --exclude='view/admin/dist' \ + --exclude='view/uniapp/node_modules' \ + pro_v3.5.1/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/ +``` + +使用密码自动化时,在 `rsync` 中指定 SSH: + +```bash +rsync -avz --delete \ + -e "sshpass -p '$DEPLOY_SSH_PASSWORD' ssh -o StrictHostKeyChecking=no" \ + --exclude='.git' \ + --exclude='.DS_Store' \ + --exclude='.env' \ + --exclude='.env-*' \ + --exclude='runtime/cache' \ + --exclude='runtime/log' \ + --exclude='runtime/temp' \ + --exclude='public/uploads' \ + --exclude='view/admin/node_modules' \ + --exclude='view/admin/dist' \ + --exclude='view/uniapp/node_modules' \ + pro_v3.5.1/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/ +``` + +线上 `.env` 不建议由代码仓库覆盖,应在服务器保留并单独维护。 + +## 7. 上传管理后台 + +```bash +rsync -avz --delete \ + pro_v3.5.1/view/admin/dist/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/public/admin/ +``` + +使用密码自动化时: + +```bash +rsync -avz --delete \ + -e "sshpass -p '$DEPLOY_SSH_PASSWORD' ssh -o StrictHostKeyChecking=no" \ + pro_v3.5.1/view/admin/dist/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/public/admin/ +``` + +## 8. 远程收尾命令 + +```bash +ssh ${DEPLOY_USER}@${DEPLOY_HOST} "\ + cd ${DEPLOY_PATH} && \ + php think clear && \ + chown -R www:www runtime public/uploads public/admin 2>/dev/null || true && \ + chmod -R 755 runtime public/admin 2>/dev/null || true" +``` + +重启后端常驻服务。按服务器实际进程管理方式选择其一: + +```bash +# 宝塔进程守护 +# 推荐在宝塔面板中重启对应的 Swoole 进程守护任务。 +# 如果宝塔进程守护任务配置了命令行启动 php think swoole,可在面板点击“重启”。 + +# 命令行兜底,仅当确认不会和宝塔进程守护冲突时使用: +pkill -f 'php think swoole' || true +cd /www/wwwroot/hjf.suzhouyuqi.com +nohup php think swoole > runtime/swoole.log 2>&1 & +``` + +当前环境使用 Swoole,PHP-FPM 不是主要入口。只有在站点同时依赖 PHP-FPM 时才需要重载: + +```bash +systemctl reload php-fpm || true +``` + +## 9. Nginx 配置要点 + +当前服务器 Nginx 已经由宝塔配置并运行正常,更新发布一般不需要修改 Nginx。下面只作为检查项和故障排查参考。 + +站点根目录应指向 `public`: + +```nginx +server { + listen 80; + listen 443 ssl http2; + server_name hjf.fsgx.cn; + root /www/wwwroot/hjf.suzhouyuqi.com/public; + index index.html index.php; + + location /admin/ { + try_files $uri $uri/ /admin/index.html; + } + + location / { + try_files $uri $uri/ /index.php?$query_string; + } + + location ~ \.php$ { + # 按服务器现有方式转发到 Swoole 或 PHP-FPM + } +} +``` + +如果管理后台访问白屏,重点检查: + +```text +/www/wwwroot/hjf.suzhouyuqi.com/public/admin/index.html +/www/wwwroot/hjf.suzhouyuqi.com/public/admin/static/ +``` + +## 10. 验证清单 + +部署完成后执行: + +```bash +curl -I https://hjf.fsgx.cn/admin +curl -I https://hjf.fsgx.cn/admin/ +curl -I https://hjf.fsgx.cn/admin/index.html +``` + +浏览器验证: + +```text +https://hjf.fsgx.cn/admin +``` + +后台登录后重点验证: + +- 商品列表可打开。 +- 商品 `type_header` 接口不再返回 `config/auth.php:82`。 +- 系统菜单、首页统计、订单列表、用户列表可以正常请求。 +- 静态资源没有返回 HTML,浏览器控制台无 `Unexpected token '<'`。 + +## 11. 一键更新部署脚本模板 + +该脚本面向“代码更新发布”,默认不修改宝塔站点配置、不覆盖线上 `.env`。Swoole 重启优先通过宝塔面板完成;脚本末尾保留 `supervisorctl`/命令行兜底示例,需要按服务器实际进程守护名称调整。 + +```bash +#!/usr/bin/env bash +set -euo pipefail + +DEPLOY_HOST="${DEPLOY_HOST:-182.92.142.158}" +DEPLOY_USER="${DEPLOY_USER:-root}" +DEPLOY_PATH="${DEPLOY_PATH:-/www/wwwroot/hjf.suzhouyuqi.com}" +SSH_CMD="ssh -o StrictHostKeyChecking=no" + +if [ -n "${DEPLOY_SSH_PASSWORD:-}" ]; then + SSH_CMD="sshpass -p ${DEPLOY_SSH_PASSWORD} ssh -o StrictHostKeyChecking=no" + RSYNC_SSH="sshpass -p ${DEPLOY_SSH_PASSWORD} ssh -o StrictHostKeyChecking=no" +else + RSYNC_SSH="ssh -o StrictHostKeyChecking=no" +fi + +git fetch origin +git checkout fsgx-bypass-auth +git pull --ff-only origin fsgx-bypass-auth + +cd pro_v3.5.1 +composer install --no-dev --prefer-dist --optimize-autoloader + +cd view/admin +npm install +npm run build +cd ../../.. + +$SSH_CMD ${DEPLOY_USER}@${DEPLOY_HOST} "\ + mkdir -p /www/backup && \ + tar -czf /www/backup/hjf_fsgx_\$(date +%Y%m%d_%H%M%S).tar.gz \ + -C /www/wwwroot hjf.suzhouyuqi.com" + +rsync -avz --delete -e "$RSYNC_SSH" \ + --exclude='.git' \ + --exclude='.DS_Store' \ + --exclude='.env' \ + --exclude='.env-*' \ + --exclude='runtime/cache' \ + --exclude='runtime/log' \ + --exclude='runtime/temp' \ + --exclude='public/uploads' \ + --exclude='view/admin/node_modules' \ + --exclude='view/admin/dist' \ + --exclude='view/uniapp/node_modules' \ + pro_v3.5.1/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/ + +rsync -avz --delete -e "$RSYNC_SSH" \ + pro_v3.5.1/view/admin/dist/ \ + ${DEPLOY_USER}@${DEPLOY_HOST}:${DEPLOY_PATH}/public/admin/ + +$SSH_CMD ${DEPLOY_USER}@${DEPLOY_HOST} "\ + cd ${DEPLOY_PATH} && \ + php think clear && \ + chown -R www:www runtime public/uploads public/admin 2>/dev/null || true && \ + chmod -R 755 runtime public/admin 2>/dev/null || true && \ + echo '请通过宝塔进程守护重启 Swoole 服务'" + +curl -I https://hjf.fsgx.cn/admin +``` + +## 12. 回滚 + +查看备份: + +```bash +ssh ${DEPLOY_USER}@${DEPLOY_HOST} "ls -lh /www/backup | grep hjf_fsgx" +``` + +回滚示例: + +```bash +ssh ${DEPLOY_USER}@${DEPLOY_HOST} "\ + cd /www/wwwroot && \ + mv hjf.suzhouyuqi.com hjf.suzhouyuqi.com.bad.$(date +%Y%m%d_%H%M%S) && \ + mkdir -p hjf.suzhouyuqi.com && \ + tar -xzf /www/backup/备份文件名.tar.gz -C /www/wwwroot && \ + supervisorctl restart hjfshop-swoole || true" +``` diff --git a/pro_v3.5.1/.env-fsgx b/pro_v3.5.1/.env-fsgx new file mode 100644 index 00000000..03d03687 --- /dev/null +++ b/pro_v3.5.1/.env-fsgx @@ -0,0 +1,45 @@ +APP_DEBUG = true +DEFAULT_LANG = zh-cn + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai +APP_KEY = 6cbfc3f329ebdee85e045c2e07ea5cfe +SYS_SECURE = false + +[DATABASE] +DRIVER = mysql +TYPE = mysql +HOSTNAME = 47.94.76.64 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = 8c4651a2cfce9076 +DATABASE = fsgx-shop +PREFIX = eb_ +CHARSET = utf8mb4 +DEBUG = true + +[REDIS] +HOSTNAME = 47.94.76.64 +PORT = 6379 +PASSWORD = 123456 +SELECT = 0 +PREFIX = 0187f3f97e956474526ccb9655799ba4 + + +#微信支付证书配置 +[RECEPTACLE] +ENABLE = false +PAYCERT = #PAYCERT# +PAYKEY = #PAYKEY# + +[QUEUE] +ENABLE = false + +[TIMER] +ENABLE = false + + +[QUEUE] +ENABLE = false +LISTEN_NAME = CRMEB_PRO +BATCH_LISTEN_NAME = CRMEB_PRO_BATCH diff --git a/pro_v3.5.1/.env-huangjinfen b/pro_v3.5.1/.env-huangjinfen new file mode 100644 index 00000000..98295013 --- /dev/null +++ b/pro_v3.5.1/.env-huangjinfen @@ -0,0 +1,45 @@ +APP_DEBUG = true +DEFAULT_LANG = zh-cn + +[APP] +DEFAULT_TIMEZONE = Asia/Shanghai +APP_KEY = 6cbfc3f329ebdee85e045c2e07ea5cfe +SYS_SECURE = false + +[DATABASE] +DRIVER = mysql +TYPE = mysql +HOSTNAME = 182.92.142.158 +HOSTPORT = 3306 +USERNAME = root +PASSWORD = 50401beb19713d5e +DATABASE = hjfshop +PREFIX = eb_ +CHARSET = utf8mb4 +DEBUG = true + +[REDIS] +HOSTNAME = 182.92.142.158 +PORT = 6379 +PASSWORD = 123456 +SELECT = 0 +PREFIX = 0187f3f97e956474526ccb9655799ba4 + + +#微信支付证书配置 +[RECEPTACLE] +ENABLE = false +PAYCERT = #PAYCERT# +PAYKEY = #PAYKEY# + +[QUEUE] +ENABLE = false + +[TIMER] +ENABLE = false + + +[QUEUE] +ENABLE = false +LISTEN_NAME = CRMEB_PRO +BATCH_LISTEN_NAME = CRMEB_PRO_BATCH