From 312c7ff68123171f4c35be45e0b7adc8e1e4cd34 Mon Sep 17 00:00:00 2001 From: aiyimickey <39365912+aiyimickey@users.noreply.github.com> Date: Thu, 2 Jul 2026 11:25:33 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20shared=20=E5=85=B1=E4=BA=AB?= =?UTF-8?q?=E5=BA=93=E7=BB=9F=E4=B8=80=E7=AE=A1=E7=90=86=EF=BC=8C=E5=BF=AB?= =?UTF-8?q?=E7=85=A7=E6=AF=94=E5=AF=B9=E9=81=BF=E5=85=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=EF=BC=9B=E6=89=80=E6=9C=89=20Next.js=20?= =?UTF-8?q?=E7=AB=99=E7=82=B9=E8=87=AA=E5=8A=A8=E5=8F=97=E7=9B=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- deploy-ai.sh | 63 ++++++++++++++++++++++++++++++--- deploy-monitor.sh | 89 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 4 deletions(-) create mode 100644 deploy-monitor.sh diff --git a/deploy-ai.sh b/deploy-ai.sh index 9af5dd8..ae6626f 100755 --- a/deploy-ai.sh +++ b/deploy-ai.sh @@ -226,12 +226,60 @@ ENVEOF SNAPSHOT_FILE="/tmp/.snapshot.${SITE}.md5" BUILD_START=$(date +%s) +# ============================================================ +# 同步 shared 共享库(快照比对,无变化跳过) +# ============================================================ +SHARED_SNAPSHOT="/tmp/.snapshot.shared.md5" +SHARED_LOCAL="/Users/niuniu/programs/docker/shared" +SHARED_REMOTE="/root/docker/shared" + +sync_shared() { + # 统一管理 /root/docker/shared/,各站点通过 shared -> ../shared 符号链接自动解析 + + info "检查 shared 共享库..." + local local_md5 + local_md5=$(find "$SHARED_LOCAL" \ + -not -path '*/node_modules/*' \ + -not -path '*/.git/*' \ + -not -name '._*' \ + -type f \ + -exec md5 -q {} \; 2>/dev/null \ + | sort \ + | md5 -q) + + local prev_md5 + prev_md5=$(ssh txjp "cat ${SHARED_SNAPSHOT} 2>/dev/null" 2>/dev/null || echo "") + + if [[ "$prev_md5" == "$local_md5" ]]; then + # shared 无变化,仅确保目录存在(防止首次部署或手动清理后死链接) + ssh txjp "test -d ${SHARED_REMOTE}/lib || (mkdir -p ${SHARED_REMOTE} && echo 'shared 目录异常但快照存在,已恢复空目录')" 2>/dev/null + return 0 + fi + + if [[ -z "$prev_md5" ]]; then + info "shared 首次部署,上传..." + else + info "shared 有变化,上传..." + fi + + COPYFILE_DISABLE=1 tar czf /tmp/shared-deploy.tar.gz -C /Users/niuniu/programs/docker \ + --exclude='node_modules' --exclude='.git' --exclude='._*' shared/ 2>/dev/null + scp /tmp/shared-deploy.tar.gz txjp:/tmp/shared-deploy.tar.gz + ssh txjp "rm -rf ${SHARED_REMOTE} && mkdir -p ${SHARED_REMOTE} && \ + tar xzf /tmp/shared-deploy.tar.gz -C /root/docker/ && \ + echo '${local_md5}' > ${SHARED_SNAPSHOT}" + log "shared 已同步到 ${SHARED_REMOTE}" +} + build_on_server() { local extra_env="${1:-}" - # 1. 计算源码快照 + # 0. 同步 shared 共享库(所有使用 @shared 的站点自动受益) + sync_shared + + # 1. 计算源码快照(含 shared,确保 shared 变化也触发重构建) log "检查源码是否有变化..." - local_md5=$(find "$LOCAL_DIR" \ + local_md5=$( (find "$LOCAL_DIR" \ -not -path '*/node_modules/*' \ -not -path '*/.next/*' \ -not -path '*/out/*' \ @@ -242,7 +290,13 @@ build_on_server() { -not -path '*/.git/*' \ -not -name '._*' \ -type f \ - -exec md5 -q {} \; \ + -exec md5 -q {} \; ; \ + find "$SHARED_LOCAL" \ + -not -path '*/node_modules/*' \ + -not -path '*/.git/*' \ + -not -name '._*' \ + -type f \ + -exec md5 -q {} \; 2>/dev/null) \ | sort \ | md5 -q) echo " 源码快照: ${local_md5}" @@ -414,7 +468,8 @@ build_on_server() { # 7. 清理构建产生的悬空镜像和缓存(根据磁盘使用率动态调整) log "清理构建缓存..." - ssh txjp "docker image prune -f --filter 'label=com.docker.compose.project=${SITE}-ai' 2>/dev/null || true" + # 清理悬空镜像(无标签或未被引用的中间层) + ssh txjp "docker image prune -f 2>/dev/null || true" # 根据磁盘使用率动态调整构建缓存清理策略 DISK_USAGE=$(ssh txjp "df / --output=pcent | tail -1 | tr -d ' %'" 2>/dev/null || echo "50") diff --git a/deploy-monitor.sh b/deploy-monitor.sh new file mode 100644 index 0000000..8bcfbb2 --- /dev/null +++ b/deploy-monitor.sh @@ -0,0 +1,89 @@ +#!/bin/bash +# deploy-monitor.sh — 部署 monitor-ai 到云服务器 +# 用法: bash deploy-monitor.sh [--remote --host ] [--dev] +set -e + +MODE="${1:-local}" +REMOTE_HOST="" +PROJECT_DIR="$(cd "$(dirname "$0")/.." && pwd)" +MONITOR_DIR="$PROJECT_DIR/monitor-ai" +SHARED_DIR="$PROJECT_DIR/shared" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) + +# 解析参数 +while [[ $# -gt 0 ]]; do + case $1 in + --remote) MODE="remote"; shift ;; + --host) REMOTE_HOST="$2"; shift 2 ;; + --dev) MODE="dev"; shift ;; + *) shift ;; + esac +done + +echo "=== deploy-monitor.sh === Mode: $MODE ===" + +# 打包源码 +echo "[1/5] 打包源码..." +TARBALL="/tmp/monitor-ai-${TIMESTAMP}.tar.gz" +cd "$PROJECT_DIR" +tar czf "$TARBALL" --exclude='node_modules' --exclude='.next' --exclude='data/*.db' \ + shared/lib/ monitor-ai/ + +echo "[2/5] 上传..." +if [ "$MODE" = "remote" ]; then + if [ -z "$REMOTE_HOST" ]; then + echo "Error: --remote 模式需要 --host " + exit 1 + fi + ssh "$REMOTE_HOST" "mkdir -p /root/docker" + scp "$TARBALL" "$REMOTE_HOST:/root/docker/" + ssh "$REMOTE_HOST" "cd /root/docker && tar xzf monitor-ai-${TIMESTAMP}.tar.gz && rm monitor-ai-${TIMESTAMP}.tar.gz" +else + # local 模式: 部署到当前服务器的 /root/docker/ + sudo mkdir -p /root/docker + sudo cp "$TARBALL" /root/docker/ + cd /root/docker + sudo tar xzf "monitor-ai-${TIMESTAMP}.tar.gz" + sudo rm "monitor-ai-${TIMESTAMP}.tar.gz" +fi + +echo "[3/5] 构建..." +if [ "$MODE" = "remote" ]; then + ssh "$REMOTE_HOST" "cd /root/docker/monitor-ai && npm install && npm run build" +else + cd /root/docker/monitor-ai + sudo npm install + sudo npm run build +fi + +echo "[4/5] 配置首次部署..." +if [ "$MODE" = "remote" ]; then + # 生成密钥 + OIDC_SECRET=$(openssl rand -hex 32) + LOCALADMIN_PWD=$(openssl rand -hex 16) + ssh "$REMOTE_HOST" "cd /root/docker/monitor-ai && \ + echo 'NODE_ENV=production' > .env && \ + echo 'DATABASE_PATH=/data/monitor.db' >> .env && \ + echo 'MONITOR_MODE=local' >> .env && \ + echo 'AUTHELIA_URL=https://sso.tlyq.ai' >> .env && \ + echo 'OIDC_CLIENT_ID=monitor-oidc' >> .env && \ + echo 'OIDC_CLIENT_SECRET=${OIDC_SECRET}' >> .env && \ + echo 'OIDC_REDIRECT_URI=https://monitor.tlyq.ai/api/auth/callback' >> .env && \ + echo 'JWT_SECRET=<与全站一致>' >> .env && \ + echo 'COOKIE_DOMAIN=.tlyq.ai' >> .env && \ + echo 'LDAP_URL=ldap://ldap-ai:3890' >> .env && \ + echo 'LOCALADMIN_PASSWORD=${LOCALADMIN_PWD}' >> .env && \ + echo 'NODE_TLS_REJECT_UNAUTHORIZED=0' >> .env" +fi + +echo "[5/5] 启动容器..." +if [ "$MODE" = "remote" ]; then + ssh "$REMOTE_HOST" "cd /root/docker/monitor-ai && docker compose up -d --build" +else + cd /root/docker/monitor-ai + sudo docker compose up -d --build +fi + +echo "=== 部署完成 ===" +echo "monitor-ai: https://monitor.tlyq.ai" +echo "健康检查: curl https://monitor.tlyq.ai/api/health"