shuangyan-notebook/第五域 · Fifth Domain/⚒️ 铸渊·协作指令|GitHub ↔ Notion 桥接协议/⚒️ 铸渊指令|服务器沙盒初始化 · 现有模块迁移到DEV编号目录(2026-03-15·曜冥签发) 324fb92f3831814e962fd3035cf6b5bf.md
Guanghu Domestic Migration a27e87cb99 chore: import sanitized domestic snapshot for REPO-007
Source snapshot: 97d7f0fae96dc04b7ddad56fc1db6a108ed662cc

[SEC-CLEAN] · pre-push-clean v1.0 · 109处敏感信息已自动转乱码
2026-07-17 15:59:55 +08:00

16 KiB
Raw Permalink Blame History

belongs_to: - "INDEX · 铸渊·协作指令GitHub ↔ Notion 桥接协议" related_to: - ""

⚒️ 铸渊指令|服务器沙盒初始化 · 现有模块迁移到DEV编号目录2026-03-15·曜冥签发

⚠️ 本指令受「服务器部署适配协议 v1.0」约束。


签发信息

项目 内容
签发 曜冥ICE-GL-YM001 ∞)· 2026-03-15
优先级 P0 · 立即执行
前置 铸渊唤醒核心大脑 → 扫描 Secrets → 确认 DEPLOY_HOST / DEPLOY_USER / DEPLOY_KEY 可用
配套协议 服务器部署适配协议 v1.0
配套指令 沙盒部署自动化闭环 v1.0
核心目标 把服务器从「一锅乱炖」变成「每人一间房」· 现有模块迁移到 DEV 编号沙盒目录

一、当前问题

服务器上现有模块全部平铺在 /var/www/hololake-frontend/ 下,没有按开发者编号隔离。每次部署出问题,分不清谁的、谁改的、谁修的。妈妈变成了全团队的运维工程师。

这条指令的目的:一次性把服务器整理干净,以后每个开发者只能在自己的沙盒里折腾。


二、铸渊执行脚本SSH到服务器·读到就做

Step 1 · 探查现状(先看再动)

#!/bin/bash
# step1-survey.sh · 探查服务器现状
# 铸渊SSH到服务器后第一步执行

echo "===== 🔍 服务器目录探查 · $(date '+%Y-%m-%d %H:%M') ====="

echo ""
echo "📂 /var/www/ 顶层目录:"
ls -la /var/www/

echo ""
echo "📂 /var/www/hololake-frontend/ 内容:"
ls -la /var/www/hololake-frontend/ 2>/dev/null || echo "⚠️ 目录不存在"

echo ""
echo "📂 /var/www/backend/ 内容:"
ls -la /var/www/backend/ 2>/dev/null || echo "⚠️ 目录不存在"

echo ""
echo "📂 /var/www/feishu-bot/ 内容:"
ls -la /var/www/feishu-bot/ 2>/dev/null || echo "⚠️ 目录不存在"

echo ""
echo "📂 /opt/guanghulab-dingtalk/ 内容:"
ls -la /opt/guanghulab-dingtalk/ 2>/dev/null || echo "⚠️ 目录不存在"

echo ""
echo "📂 查找所有 index.html定位已部署模块"
find /var/www/ -name 'index.html' -type f 2>/dev/null

echo ""
echo "📂 Nginx 配置(定位现有路由):"
cat /etc/nginx/conf.d/hololake.conf 2>/dev/null || cat /etc/nginx/nginx.conf 2>/dev/null | head -100

echo ""
echo "📂 PM2 进程列表(定位运行中的后端服务):"
pm2 list 2>/dev/null || echo "⚠️ PM2 未安装或无进程"

echo ""
echo "===== ✅ 探查完成 · 根据结果执行 Step 2 ====="

铸渊:把 Step 1 的完整输出保存到仓库 data/server-survey-20260315.log,然后继续 Step 2。


Step 2 · 创建沙盒目录骨架

#!/bin/bash
# step2-create-sandboxes.sh · 创建所有开发者沙盒目录
# 严格按照部署适配协议 v1.0 执行

echo "===== 🏠 创建沙盒目录骨架 ====="

# 所有已注册开发者编号
DEV_IDS=("DEV-001" "DEV-002" "DEV-003" "DEV-004" "DEV-005" "DEV-009" "DEV-010" "DEV-011" "DEV-012" "DEV-013" "DEV-014")

for DEV_ID in "${DEV_IDS[@]}"; do
  SANDBOX="/var/www/${DEV_ID}"
  if [ -d "$SANDBOX" ]; then
    echo "⏭️ ${DEV_ID} 目录已存在,跳过"
  else
    mkdir -p "$SANDBOX"
    chown nginx:nginx "$SANDBOX"
    chmod 755 "$SANDBOX"
    
    # 生成部署身份文件
    cat > "${SANDBOX}/.deploy-profile" << EOF
{
  "dev_id": "${DEV_ID}",
  "created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
  "created_by": "zhuyuan-sandbox-init"
}
EOF
    chown nginx:nginx "${SANDBOX}/.deploy-profile"
    chmod 644 "${SANDBOX}/.deploy-profile"
    
    echo "✅ ${DEV_ID} 沙盒创建完成"
  fi
done

# 创建共享工具目录
mkdir -p /var/www/_shared
chown nginx:nginx /var/www/_shared
chmod 755 /var/www/_shared
echo "✅ _shared 目录创建完成"

echo ""
echo "===== ✅ 沙盒骨架创建完成 ====="
ls -la /var/www/

Step 3 · 迁移现有模块(先复制再切换·不直接移动)

#!/bin/bash
# step3-migrate-modules.sh · 迁移现有模块到沙盒
# ⚠️ 核心原则:先复制 → 验证 → 再切 Nginx → 最后清旧

echo "===== 📦 模块迁移开始 ====="

# ━━━ DEV-005 小草莓 ━━━
# status-board
if [ -d "/var/www/hololake-frontend/status-board" ]; then
  echo "📦 迁移 status-board → DEV-005"
  cp -r /var/www/hololake-frontend/status-board/ /var/www/DEV-005/status-board/
  chown -R nginx:nginx /var/www/DEV-005/status-board/
  find /var/www/DEV-005/status-board/ -type d -exec chmod 755 {} \;
  find /var/www/DEV-005/status-board/ -type f -exec chmod 644 {} \;
  echo "✅ status-board 已复制到 /var/www/DEV-005/status-board/"
else
  echo "⚠️ /var/www/hololake-frontend/status-board 不存在,跳过"
fi

# cost-control
if [ -d "/var/www/hololake-frontend/cost-control" ]; then
  echo "📦 迁移 cost-control → DEV-005"
  cp -r /var/www/hololake-frontend/cost-control/ /var/www/DEV-005/cost-control/
  chown -R nginx:nginx /var/www/DEV-005/cost-control/
  find /var/www/DEV-005/cost-control/ -type d -exec chmod 755 {} \;
  find /var/www/DEV-005/cost-control/ -type f -exec chmod 644 {} \;
  echo "✅ cost-control 已复制到 /var/www/DEV-005/cost-control/"
else
  echo "⚠️ /var/www/hololake-frontend/cost-control 不存在,跳过"
fi

# persona-scheduler如果存在
if [ -d "/var/www/hololake-frontend/persona-scheduler" ]; then
  echo "📦 迁移 persona-scheduler → DEV-005"
  cp -r /var/www/hololake-frontend/persona-scheduler/ /var/www/DEV-005/persona-scheduler/
  chown -R nginx:nginx /var/www/DEV-005/persona-scheduler/
  find /var/www/DEV-005/persona-scheduler/ -type d -exec chmod 755 {} \;
  find /var/www/DEV-005/persona-scheduler/ -type f -exec chmod 644 {} \;
  echo "✅ persona-scheduler 已复制到 /var/www/DEV-005/persona-scheduler/"
fi

# ━━━ 其他开发者的模块 ━━━
# 根据 Step 1 探查结果,如果 hololake-frontend/ 下发现更多模块,
# 铸渊根据模块指纹注册表或广播记录判断归属,按同样方式迁移。
# 不确定归属的模块 → 复制到 /var/www/_shared/unassigned/ 暂存

mkdir -p /var/www/_shared/unassigned

# 遍历 hololake-frontend 下所有子目录,检查是否已迁移
if [ -d "/var/www/hololake-frontend" ]; then
  for DIR in /var/www/hololake-frontend/*/; do
    DIRNAME=$(basename "$DIR")
    # 跳过已处理的
    if [[ "$DIRNAME" == "status-board" || "$DIRNAME" == "cost-control" || "$DIRNAME" == "persona-scheduler" ]]; then
      continue
    fi
    echo "⚠️ 发现未归属模块:$DIRNAME → 暂存到 _shared/unassigned/"
    cp -r "$DIR" "/var/www/_shared/unassigned/${DIRNAME}/"
  done
fi

echo ""
echo "===== ✅ 模块迁移完成 ====="
echo ""
echo "📋 迁移后各沙盒内容:"
for DEV_ID in DEV-001 DEV-002 DEV-003 DEV-004 DEV-005 DEV-009 DEV-010 DEV-011 DEV-012 DEV-013 DEV-014; do
  echo "--- ${DEV_ID} ---"
  ls /var/www/${DEV_ID}/ 2>/dev/null || echo "  (空)"
done

if [ -d "/var/www/_shared/unassigned" ]; then
  echo "--- 未归属模块 ---"
  ls /var/www/_shared/unassigned/ 2>/dev/null
fi

Step 4 · 部署自检脚本和冒烟检查脚本

#!/bin/bash
# step4-deploy-scripts.sh · 部署共享脚本

echo "===== 🔧 部署共享脚本 ====="

# deploy-check.sh从部署适配协议 v1.0 复制)
# 铸渊从仓库 scripts/deploy-check.sh 复制到服务器
scp scripts/deploy-check.sh root@8.155.62.235:/var/www/_shared/deploy-check.sh
ssh root@8.155.62.235 "chmod +x /var/www/_shared/deploy-check.sh"

# smoke-test.sh从部署适配协议 v1.0 复制)
scp scripts/smoke-test.sh root@8.155.62.235:/var/www/_shared/smoke-test.sh
ssh root@8.155.62.235 "chmod +x /var/www/_shared/smoke-test.sh"

echo "✅ 共享脚本部署完成"

Step 5 · 更新 Nginx 配置(最关键的一步)

#!/bin/bash
# step5-update-nginx.sh · 更新 Nginx 路由到新沙盒结构
# ⚠️ 先备份 → 再改 → 再测 → 再reload

echo "===== 🔧 更新 Nginx 配置 ====="

# Step 5a: 备份当前配置
NGINX_CONF="/etc/nginx/conf.d/hololake.conf"
BACKUP="/etc/nginx/conf.d/hololake.conf.bak.$(date +%Y%m%d%H%M)"
cp "$NGINX_CONF" "$BACKUP"
echo "✅ 配置已备份到 $BACKUP"

# Step 5b: 生成沙盒 location 块
# 铸渊需要在 hololake.conf 的 server 块中添加以下 location

# ━━━ 新增内容(追加到 server 块内,在最后一个 location 之前)━━━

# --- 开发者沙盒路由 ---
# DEV-001 页页
# location /DEV-001/ {
#     alias /var/www/DEV-001/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-002 肥猫
# location /DEV-002/ {
#     alias /var/www/DEV-002/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-003 燕樊
# location /DEV-003/ {
#     alias /var/www/DEV-003/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-004 之之
# location /DEV-004/ {
#     alias /var/www/DEV-004/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-005 小草莓
# location /DEV-005/ {
#     alias /var/www/DEV-005/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-009 花尔
# location /DEV-009/ {
#     alias /var/www/DEV-009/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-010 桔子
# location /DEV-010/ {
#     alias /var/www/DEV-010/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-011 匆匆那年
# location /DEV-011/ {
#     alias /var/www/DEV-011/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-012 Awen
# location /DEV-012/ {
#     alias /var/www/DEV-012/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-013 小兴
# location /DEV-013/ {
#     alias /var/www/DEV-013/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# DEV-014 时雨
# location /DEV-014/ {
#     alias /var/www/DEV-014/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# --- 模块快捷路径(指向新沙盒位置)---
# location /status-board/ {
#     alias /var/www/DEV-005/status-board/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# location /cost-control/ {
#     alias /var/www/DEV-005/cost-control/;
#     index index.html;
#     try_files $uri $uri/ =404;
# }

# ⚠️ 铸渊注意:
# 1. 以上 location 块需要写入实际的 hololake.conf 文件中(去掉注释符号)
# 2. 如果旧配置中已有 /status-board/ 和 /cost-control/ 的 location
#    需要把它们的 alias 路径从旧路径改成新沙盒路径
# 3. 不要删除原有的 / 根路由和 /api/ 等后端代理路由
# 4. 清理重复的 server_name 块(之前已知有 conflicting server name 警告)

# Step 5c: 测试配置
nginx -t

# Step 5d: 如果测试通过则重载
# nginx -t 输出 "test is successful" 时才执行:
# systemctl reload nginx

echo ""
echo "⚠️ 铸渊nginx -t 通过后再执行 systemctl reload nginx"
echo "如果 nginx -t 报错恢复备份cp $BACKUP $NGINX_CONF && nginx -t"

Step 6 · 验证迁移结果

#!/bin/bash
# step6-verify.sh · 验证迁移是否成功

echo "===== 🔥 迁移验证 ====="

# 检查已迁移模块的访问
URLS=(
  "https://guanghulab.com/status-board/|DEV-005·看板新路径"
  "https://guanghulab.com/cost-control/|DEV-005·成本控制新路径"
  "https://guanghulab.com/DEV-005/status-board/|DEV-005·沙盒路由"
  "https://guanghulab.com/|主站首页"
)

FAILED=0
for entry in "${URLS[@]}"; do
  IFS='|' read -r url name <<< "$entry"
  STATUS=$(curl -o /dev/null -s -w "%{http_code}" --max-time 10 "$url")
  if [ "$STATUS" = "200" ]; then
    echo "✅ ${name}${STATUS}"
  else
    echo "❌ ${name}${STATUS} ⚠️"
    FAILED=$((FAILED+1))
  fi
done

echo ""
if [ $FAILED -eq 0 ]; then
  echo "===== ✅ 迁移验证全部通过 ====="
else
  echo "===== ❌ ${FAILED} 个路由异常 · 检查 Nginx 配置 ====="
fi

# 检查沙盒目录权限
echo ""
echo "📋 沙盒目录权限检查:"
for DEV_ID in DEV-001 DEV-002 DEV-003 DEV-004 DEV-005 DEV-009 DEV-010 DEV-011 DEV-012 DEV-013 DEV-014; do
  OWNER=$(stat -c '%U:%G' /var/www/${DEV_ID} 2>/dev/null)
  PERM=$(stat -c '%a' /var/www/${DEV_ID} 2>/dev/null)
  if [ "$OWNER" = "nginx:nginx" ] && [ "$PERM" = "755" ]; then
    echo "✅ ${DEV_ID}${OWNER} ${PERM}"
  else
    echo "❌ ${DEV_ID}${OWNER:-不存在} ${PERM:-N/A}"
  fi
done

Step 7 · 清理旧路径(验证通过后才执行)

#!/bin/bash
# step7-cleanup.sh · 清理旧路径
# ⚠️ 只有 Step 6 全部 ✅ 通过后才执行本步骤

echo "===== 🧹 清理旧路径 ====="
echo "⚠️ 确认 Step 6 验证全部通过后才继续"

# 不删除 hololake-frontend 整个目录,先重命名为备份
if [ -d "/var/www/hololake-frontend" ]; then
  mv /var/www/hololake-frontend /var/www/hololake-frontend.bak.$(date +%Y%m%d)
  echo "✅ 旧目录已重命名为 hololake-frontend.bak.$(date +%Y%m%d)"
  echo "→ 7天后如无问题可手动删除"
fi

echo "===== ✅ 清理完成 ====="

三、执行顺序(铸渊严格按顺序)

步骤 脚本 前置条件 失败处理
Step 1 step1-survey.sh SSH连上服务器 保存日志到仓库,继续
Step 2 step2-create-sandboxes.sh Step 1 完成 如果某个目录创建失败,记录并继续其他
Step 3 step3-migrate-modules.sh Step 2 完成 复制失败的模块记录到日志,不阻断
Step 4 step4-deploy-scripts.sh Step 3 完成 脚本不存在则先在仓库创建
Step 5 step5-update-nginx.sh Step 3 完成 nginx -t 失败 → 立即恢复备份 → 停止
Step 6 step6-verify.sh Step 5 完成且 nginx reload 成功 有失败 → 回滚 Nginx 配置 → 排查
Step 7 step7-cleanup.sh Step 6 全部 不删除,只重命名

四、铸渊自行部署清单(读到就做)

铸渊自行部署清单(读到就做·不等人):

① 在仓库创建脚本文件
   a. scripts/sandbox-init/step1-survey.sh
   b. scripts/sandbox-init/step2-create-sandboxes.sh
   c. scripts/sandbox-init/step3-migrate-modules.sh
   d. scripts/sandbox-init/step4-deploy-scripts.sh
   e. scripts/sandbox-init/step5-update-nginx.sh
   f. scripts/sandbox-init/step6-verify.sh
   g. scripts/sandbox-init/step7-cleanup.sh

② 创建一次性 Workflow 执行迁移
   a. .github/workflows/sandbox-init.yml
   b. 触发方式workflow_dispatch手动触发因为是一次性操作
   c. 按 Step 1→7 顺序执行
   d. 每步输出保存为 artifact

③ 执行 Workflow · 完成迁移

④ 把迁移结果写入仓库
   a. data/server-survey-20260315.log
   b. data/sandbox-migration-report.json

⑤ 更新 dev-registry.json
   a. 补全所有11位开发者的沙盒路径

验收标准:
✅ 11个 DEV 编号目录全部创建完成 · 权限 nginx:nginx 755
✅ 小草莓的 status-board 和 cost-control 已在 /var/www/DEV-005/ 下
✅ guanghulab.com/status-board/ 访问正常200
✅ guanghulab.com/DEV-005/status-board/ 访问正常200
✅ _shared 目录和自检脚本已就位
✅ 旧目录已备份(不删除)
✅ Nginx 无 conflicting server name 警告

五、给妈妈的说明

妈妈不需要做任何事。铸渊读到这条指令就会自动执行。

执行完成后:

  • 每个开发者有自己的 /var/www/DEV-XXX/ 目录
  • 以后开发者部署模块只往自己的目录里放
  • 模块出问题 = 自己的问题 = 自己修
  • 妈妈不再修任何人的模块

后续配合「沙盒部署自动化闭环 v1.0」,开发者 push 代码就自动部署到自己的沙盒。全程无人。


⚒️ 铸渊,这是国土规划的第一步。把领土划清楚,每人一间房,以后才能自动化。

「无沙盒不部署,无编号不上线。」