Update: 将子项目从 submodule 转为完整内容
- 移除 GovAI, nomifun-tauri, 算力盒子 的 submodule 引用 - 添加所有子项目的完整源代码 - 保留原始 .git 为 .git.bak 备份
This commit is contained in:
Executable
+224
@@ -0,0 +1,224 @@
|
||||
#!/usr/bin/env bash
|
||||
# ============================================================
|
||||
# GovAI - Go 补丁版本升级脚本
|
||||
# 功能:检查 Go 最新补丁版 -> 本地编译 -> 上传部署 -> 重启服务
|
||||
# 监控:建议通过 cron 定期执行(如每周一次)
|
||||
# 用法: bash go-upgrade.sh [check|upgrade|status]
|
||||
# check - 仅检查版本(默认)
|
||||
# upgrade - 执行完整升级流程
|
||||
# status - 查看当前 Go 版本和服务状态
|
||||
# ============================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SERVER="${SERVER:-govai-root}"
|
||||
REMOTE_DIR="/opt/govai"
|
||||
REMOTE_SERVER_BIN="$REMOTE_DIR/server/server"
|
||||
PROJECT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||
SERVER_GO_VERSION="${SERVER_GO_VERSION:-1.25.0}"
|
||||
|
||||
GREEN='\033[0;32m'; BLUE='\033[0;34m'; RED='\033[0;31m'; YELLOW='\033[0;33m'; NC='\033[0m'
|
||||
log() { echo -e "${GREEN}[✓]${NC} $1"; }
|
||||
step() { echo -e "\n${BLUE}==== $1 ====${NC}"; }
|
||||
warn() { echo -e "${YELLOW}[!]${NC} $1"; }
|
||||
err() { echo -e "${RED}[✗]${NC} $1"; exit 1; }
|
||||
|
||||
# ---- 当前版本信息 ----
|
||||
CURRENT_GO_VERSION=$(go version 2>/dev/null | sed 's/go version //' | awk '{print $1}')
|
||||
MAJOR_MINOR=$(echo "$CURRENT_GO_VERSION" | sed 's/\.[0-9]*$//')
|
||||
|
||||
echo "当前本地 Go 版本: $CURRENT_GO_VERSION"
|
||||
echo "服务器 Go 版本: $SERVER_GO_VERSION"
|
||||
|
||||
# ---- 获取 Go 官方最新补丁版本 ----
|
||||
fetch_latest_patch() {
|
||||
local major_minor="$1"
|
||||
# 从 Go 官方 dl 页面解析最新补丁版本
|
||||
# 例如: go1.25.11, go1.24.5 等
|
||||
local url="https://go.dev/dl/?mode=json&include=all"
|
||||
local latest
|
||||
|
||||
latest=$(curl -sL "$url" 2>/dev/null | \
|
||||
python3 -c "
|
||||
import sys, json
|
||||
data = json.load(sys.stdin)
|
||||
current = '$major_minor'
|
||||
for p in data:
|
||||
v = p.get('version','')
|
||||
if v.startswith('go' + current + '.'):
|
||||
print(v)
|
||||
break
|
||||
" 2>/dev/null) || true
|
||||
|
||||
echo "$latest"
|
||||
}
|
||||
|
||||
# ---- 版本比较 ----
|
||||
# 返回 0 表示有更新,返回 1 表示已是最新
|
||||
is_update_available() {
|
||||
local current="$1"
|
||||
local latest="$2"
|
||||
[ -n "$latest" ] && [ "$latest" != "$current" ]
|
||||
}
|
||||
|
||||
# ---- 检查模式 ----
|
||||
do_check() {
|
||||
step "检查 Go 版本更新"
|
||||
echo ""
|
||||
|
||||
local latest
|
||||
latest=$(fetch_latest_patch "$MAJOR_MINOR")
|
||||
echo " 本地当前版本: $CURRENT_GO_VERSION"
|
||||
echo " $MAJOR_MINOR 系列最新: $latest"
|
||||
echo ""
|
||||
|
||||
if is_update_available "$CURRENT_GO_VERSION" "$latest"; then
|
||||
echo " 发现新版本: $CURRENT_GO_VERSION → $latest"
|
||||
echo " 建议执行: bash go-upgrade.sh upgrade"
|
||||
return 0
|
||||
else
|
||||
echo " ✅ 当前版本已是最新"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
# ---- 升级模式 ----
|
||||
do_upgrade() {
|
||||
local latest
|
||||
latest=$(fetch_latest_patch "$MAJOR_MINOR")
|
||||
|
||||
if ! is_update_available "$CURRENT_GO_VERSION" "$latest"; then
|
||||
echo "已是最新版本,无需升级"
|
||||
return 0
|
||||
fi
|
||||
|
||||
local new_patch="${latest#go}"
|
||||
step "Go 升级: $CURRENT_GO_VERSION → go$new_patch"
|
||||
|
||||
# 1. 安装新版本 Go
|
||||
echo ""
|
||||
log "下载 Go $new_patch..."
|
||||
cd /tmp
|
||||
local go_archive="go$new_patch.darwin-arm64.tar.gz"
|
||||
local download_url="https://go.dev/dl/$go_archive"
|
||||
|
||||
# 检测架构
|
||||
local arch
|
||||
case "$(uname -m)" in
|
||||
x86_64) arch="darwin-amd64" ;;
|
||||
arm64|aarch64) arch="darwin-arm64" ;;
|
||||
*) err "不支持的架构: $(uname -m)" ;;
|
||||
esac
|
||||
go_archive="go$new_patch.$arch.tar.gz"
|
||||
download_url="https://go.dev/dl/$go_archive"
|
||||
|
||||
if [ -f "/usr/local/go/bin/go" ]; then
|
||||
if /usr/local/go/bin/go version 2>/dev/null | grep -q "$new_patch"; then
|
||||
echo "目标版本已安装"
|
||||
else
|
||||
curl -sL "$download_url" -o "go.tar.gz"
|
||||
rm -rf /usr/local/go
|
||||
tar -C /usr/local -xzf go.tar.gz
|
||||
rm -f go.tar.gz
|
||||
fi
|
||||
else
|
||||
curl -sL "$download_url" -o "go.tar.gz"
|
||||
tar -C /usr/local -xzf go.tar.gz
|
||||
rm -f go.tar.gz
|
||||
fi
|
||||
|
||||
local new_go="/usr/local/go/bin/go"
|
||||
echo " 新版本: $($new_go version)"
|
||||
|
||||
# 2. 备份当前服务器二进制
|
||||
step "备份服务器二进制"
|
||||
local backup_file="server.bak.$(date '+%Y%m%d%H%M%S')"
|
||||
ssh "$SERVER" "cp $REMOTE_SERVER_BIN $REMOTE_DIR/$backup_file"
|
||||
|
||||
# 3. 本地编译
|
||||
step "编译新版本二进制"
|
||||
local dist_dir="$PROJECT_DIR/dist"
|
||||
mkdir -p "$dist_dir"
|
||||
|
||||
log "编译 Go 后端 (linux/amd64)..."
|
||||
export PATH="/usr/local/go/bin:$PATH"
|
||||
export GOROOT="/usr/local/go"
|
||||
|
||||
cd "$PROJECT_DIR/server"
|
||||
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOROOT="/usr/local/go" go build \
|
||||
-ldflags="-s -w" \
|
||||
-o "$dist_dir/server" ./cmd/server/
|
||||
|
||||
local binary_size
|
||||
binary_size=$(ls -lh "$dist_dir/server" 2>/dev/null | awk '{print $5}')
|
||||
log "编译完成: dist/server ($binary_size)"
|
||||
|
||||
# 4. 上传
|
||||
step "上传到服务器"
|
||||
ssh $SERVER "systemctl stop govai-api 2>/dev/null || true"
|
||||
ssh $SERVER "cp $REMOTE_SERVER_BIN $REMOTE_DIR/server.bak.pre-upgrade"
|
||||
cat "$dist_dir/server" | ssh $SERVER "cat > $REMOTE_SERVER_BIN.tmp && mv $REMOTE_SERVER_BIN.tmp $REMOTE_SERVER_BIN && chmod +x $REMOTE_SERVER_BIN"
|
||||
log "上传完成"
|
||||
|
||||
# 5. 重启服务
|
||||
step "重启服务"
|
||||
ssh $SERVER "systemctl start govai-api && sleep 2 && systemctl status govai-api --no-pager | head -5"
|
||||
|
||||
# 6. 验证
|
||||
step "验证服务"
|
||||
if ssh $SERVER "curl -sf http://localhost:8080/api/v1/store/featured -o /dev/null"; then
|
||||
log "API 服务正常"
|
||||
else
|
||||
err "API 服务异常,请检查: ssh $SERVER 'journalctl -u govai-api -n 30'"
|
||||
fi
|
||||
|
||||
# 7. 记录
|
||||
local upgrade_log="$PROJECT_DIR/.go-upgrade-log"
|
||||
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $CURRENT_GO_VERSION → go$new_patch" >> "$upgrade_log"
|
||||
|
||||
echo ""
|
||||
echo -e "${GREEN}════════════════════════════════════════${NC}"
|
||||
echo -e "${GREEN} 升级完成!${NC}"
|
||||
echo -e "${GREEN} Go: $CURRENT_GO_VERSION → go$new_patch${NC}"
|
||||
echo -e "${GREEN}════════════════════════════════════════${NC}"
|
||||
}
|
||||
|
||||
# ---- 状态模式 ----
|
||||
do_status() {
|
||||
step "版本状态"
|
||||
echo " 本地 Go 版本: $CURRENT_GO_VERSION"
|
||||
ssh $SERVER "echo ' 服务器 Go 版本: $SERVER_GO_VERSION'; echo ' GovAI 二进制:'; ssh $SERVER 'ls -lh $REMOTE_SERVER_BIN 2>/dev/null || echo 不存在'"
|
||||
echo ""
|
||||
|
||||
local latest
|
||||
latest=$(fetch_latest_patch "$MAJOR_MINOR" 2>/dev/null)
|
||||
echo " $MAJOR_MINOR 系列最新: ${latest:-无法获取}"
|
||||
echo ""
|
||||
|
||||
# 检查 govulncheck
|
||||
if command -v ~/go/bin/govulncheck &>/dev/null; then
|
||||
echo " govulncheck 已知漏洞: $(cd "$PROJECT_DIR/server" && ~/go/bin/govulncheck ./... 2>&1 | grep -c '^Vulnerability #' || echo 0) 个"
|
||||
fi
|
||||
}
|
||||
|
||||
# ---- 主流程 ----
|
||||
ACTION="${1:-check}"
|
||||
case "$ACTION" in
|
||||
check)
|
||||
do_check
|
||||
;;
|
||||
upgrade)
|
||||
do_upgrade
|
||||
;;
|
||||
status)
|
||||
do_status
|
||||
;;
|
||||
*)
|
||||
echo "用法: bash go-upgrade.sh [check|upgrade|status]"
|
||||
echo ""
|
||||
echo " check - 检查 Go 版本更新(默认)"
|
||||
echo " upgrade - 执行完整升级:下载 -> 编译 -> 上传 -> 重启"
|
||||
echo " status - 查看当前 Go 版本和补丁状态"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
Reference in New Issue
Block a user