60b4c3244e
- P1: auth.go 8处Cookie补充Secure:true+SameSite,gosec 84→78 - P0: 新增go-upgrade.sh (check/upgrade/status三模式) - docs: 安全审计报告第十一章 - SAST/CVE/CWE审计结果
224 lines
7.2 KiB
Bash
Executable File
224 lines
7.2 KiB
Bash
Executable File
#!/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 |