From 26595e4e2fbec5d71ce48e4a2fc7aa6e342d8cfa Mon Sep 17 00:00:00 2001 From: yoyo Date: Wed, 3 Dec 2025 20:05:47 +0800 Subject: [PATCH] =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- install.sh | 551 +++-------------------------------------------------- vendor.sh | 220 +++++++++++++++++++++ 3 files changed, 246 insertions(+), 527 deletions(-) create mode 100755 vendor.sh diff --git a/.gitignore b/.gitignore index c7ec943..496ee2c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -test.log +.DS_Store \ No newline at end of file diff --git a/install.sh b/install.sh index f112f29..68ef6dd 100755 --- a/install.sh +++ b/install.sh @@ -434,18 +434,8 @@ install_go_from_official() { echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee -a /etc/profile > /dev/null fi - # 配置 Go 代理(使用国内镜像) - if ! grep -q "GOPROXY" /etc/profile 2>/dev/null; then - echo '' | sudo tee -a /etc/profile > /dev/null - echo '# Go 代理配置(使用国内镜像加速)' | sudo tee -a /etc/profile > /dev/null - echo 'export GOPROXY=https://goproxy.cn,direct' | sudo tee -a /etc/profile > /dev/null - echo 'export GOSUMDB=off' | sudo tee -a /etc/profile > /dev/null - fi - - # 设置当前会话的 PATH 和 GOPROXY - export PATH=$PATH:/usr/local/go/bin - export GOPROXY=https://goproxy.cn,direct - export GOSUMDB=off + # 设置当前会话的 PATH + export PATH=$PATH:/usr/local/go/bin # 验证安装 if command -v go > /dev/null 2>&1; then @@ -477,17 +467,6 @@ install_go() { # 检查 Go 版本是否可用(尝试运行 go version) if go version > /dev/null 2>&1; then echo -e "${BLUE}Go 环境正常,跳过安装流程${NC}" - # 确保 GOPROXY 已配置(如果未配置则添加) - if ! grep -q "GOPROXY" /etc/profile 2>/dev/null; then - echo -e "${BLUE}配置 Go 代理环境变量...${NC}" - echo '' | sudo tee -a /etc/profile > /dev/null - echo '# Go 代理配置(使用国内镜像加速)' | sudo tee -a /etc/profile > /dev/null - echo 'export GOPROXY=https://goproxy.cn,direct' | sudo tee -a /etc/profile > /dev/null - echo 'export GOSUMDB=off' | sudo tee -a /etc/profile > /dev/null - fi - # 设置当前会话的环境变量 - export GOPROXY=${GOPROXY:-https://goproxy.cn,direct} - export GOSUMDB=${GOSUMDB:-off} return 0 else echo -e "${YELLOW}⚠ Go 已安装但无法正常运行,尝试重新安装...${NC}" @@ -529,19 +508,6 @@ install_go() { if [ "$install_success" = true ] && command -v go > /dev/null 2>&1; then GO_VERSION=$(go version 2>/dev/null | head -1) echo -e "${GREEN}✓ Go 安装完成: ${GO_VERSION}${NC}" - - # 配置 Go 代理(使用国内镜像) - if ! grep -q "GOPROXY" /etc/profile 2>/dev/null; then - echo '' | sudo tee -a /etc/profile > /dev/null - echo '# Go 代理配置(使用国内镜像加速)' | sudo tee -a /etc/profile > /dev/null - echo 'export GOPROXY=https://goproxy.cn,direct' | sudo tee -a /etc/profile > /dev/null - echo 'export GOSUMDB=off' | sudo tee -a /etc/profile > /dev/null - fi - - # 设置当前会话的 GOPROXY - export GOPROXY=https://goproxy.cn,direct - export GOSUMDB=off - return 0 fi @@ -712,511 +678,44 @@ build_from_source() { sudo git config --global --add safe.directory "$SOURCE_DIR" 2>/dev/null || true git config --global --add safe.directory "$SOURCE_DIR" 2>/dev/null || true - # 配置 Git 使用代理(加速 GitHub 访问) - echo -e "${BLUE}配置 Git 代理(加速 GitHub 访问)...${NC}" - - # GitHub 代理镜像列表(按优先级排序) - GITHUB_PROXIES=( - "https://gh-proxy.com" - "https://githubproxy.cc" - "https://ghproxy.com" - "https://mirror.ghproxy.com" - "https://github.com.cnpmjs.org" - ) - - # 测试并选择可用的 GitHub 代理 - GITHUB_PROXY="" - for proxy in "${GITHUB_PROXIES[@]}"; do - echo -n " 测试 ${proxy}... " - # 测试代理是否可用(尝试访问 GitHub 主页) - if curl -sf --connect-timeout 3 --max-time 5 "${proxy}/https://github.com" > /dev/null 2>&1 || \ - curl -sf --connect-timeout 3 --max-time 5 "${proxy}" > /dev/null 2>&1; then - GITHUB_PROXY="$proxy" - echo -e "${GREEN}可用${NC}" - break - else - echo -e "${RED}不可用${NC}" - fi - done - - if [ -n "$GITHUB_PROXY" ]; then - # 配置 Git 使用代理 - echo -e "${GREEN}✓ 使用 GitHub 代理: ${GITHUB_PROXY}${NC}" - - # 根据不同的代理服务配置不同的 URL 格式 - if echo "$GITHUB_PROXY" | grep -q "gh-proxy.com\|githubproxy.cc"; then - # gh-proxy.com 和 githubproxy.cc 使用 /https://github.com/ 格式 - GIT_PROXY_URL="${GITHUB_PROXY}/https://github.com/" - sudo git config --global url."${GIT_PROXY_URL}".insteadOf "https://github.com/" 2>/dev/null || true - git config --global url."${GIT_PROXY_URL}".insteadOf "https://github.com/" 2>/dev/null || true - - # 配置 Git HTTP/HTTPS 代理 - sudo git config --global http.https://github.com.proxy "${GITHUB_PROXY}/" 2>/dev/null || true - git config --global http.https://github.com.proxy "${GITHUB_PROXY}/" 2>/dev/null || true - else - # 其他代理使用标准格式 - sudo git config --global url."${GITHUB_PROXY}/https://github.com/".insteadOf "https://github.com/" 2>/dev/null || true - git config --global url."${GITHUB_PROXY}/https://github.com/".insteadOf "https://github.com/" 2>/dev/null || true - - sudo git config --global http.https://github.com.proxy "${GITHUB_PROXY}/" 2>/dev/null || true - git config --global http.https://github.com.proxy "${GITHUB_PROXY}/" 2>/dev/null || true - fi - - # 设置环境变量(供 Go 使用) - export HTTP_PROXY="${GITHUB_PROXY}/" - export HTTPS_PROXY="${GITHUB_PROXY}/" - export http_proxy="${GITHUB_PROXY}/" - export https_proxy="${GITHUB_PROXY}/" - - # 配置 Git 重写 golang.org 和 google.golang.org 的 URL(通过 GitHub 代理) - # golang.org/x/* 包在 GitHub 上的镜像路径是 github.com/golang/x-* - # 例如:golang.org/x/net -> github.com/golang/net - sudo git config --global url."${GITHUB_PROXY}/https://github.com/golang/".insteadOf "https://golang.org/x/" 2>/dev/null || true - git config --global url."${GITHUB_PROXY}/https://github.com/golang/".insteadOf "https://golang.org/x/" 2>/dev/null || true - - # google.golang.org 也可以通过 GitHub 代理 - # 例如:google.golang.org/protobuf -> github.com/protocolbuffers/protobuf-go - sudo git config --global url."${GITHUB_PROXY}/https://github.com/protocolbuffers/".insteadOf "https://google.golang.org/protobuf" 2>/dev/null || true - git config --global url."${GITHUB_PROXY}/https://github.com/protocolbuffers/".insteadOf "https://google.golang.org/protobuf" 2>/dev/null || true - - # 设置环境变量,让 Go 通过代理访问这些域名 - # 注意:这需要 Go 支持 HTTP_PROXY,我们已经设置了 - - # 添加到 Go 环境变量中 - GO_ENV="$GO_ENV HTTP_PROXY=${GITHUB_PROXY}/ HTTPS_PROXY=${GITHUB_PROXY}/ http_proxy=${GITHUB_PROXY}/ https_proxy=${GITHUB_PROXY}/" - - echo -e "${BLUE}已配置 golang.org 和 google.golang.org 通过 GitHub 代理访问${NC}" - - echo -e "${BLUE}已配置 Git 和 Go 使用 GitHub 代理加速${NC}" - else - echo -e "${YELLOW}⚠ 未找到可用的 GitHub 代理,将直接访问 GitHub${NC}" - echo -e "${YELLOW}提示: 如果 GitHub 访问慢,可以手动设置代理${NC}" + # 检查 vendor 目录是否存在(必须存在) + echo -e "${BLUE}检查 vendor 目录...${NC}" + if [ ! -d "$SOURCE_DIR/vendor" ] || [ ! -f "$SOURCE_DIR/vendor/modules.txt" ]; then + echo -e "${RED}错误: vendor 目录不存在或无效${NC}" + echo -e "${RED}请确保项目包含 vendor 目录,或先运行 ./vendor.sh 创建 vendor 目录${NC}" + echo -e "${YELLOW}vendor 目录路径: ${SOURCE_DIR}/vendor${NC}" + exit 1 fi - # 配置 Go 代理(使用国内镜像) - echo -e "${BLUE}配置 Go 代理(使用国内镜像加速)...${NC}" - # Go 代理镜像列表(按优先级排序,使用多个镜像以提高成功率) - # 注意:不包含 proxy.golang.org,因为在中国大陆无法访问 - GO_PROXY_MIRRORS=( - "https://goproxy.cn,https://goproxy.io,https://mirrors.aliyun.com/go-proxy/,direct" - "https://goproxy.io,https://goproxy.cn,https://mirrors.aliyun.com/go-proxy/,direct" - "https://mirrors.aliyun.com/go-proxy/,https://goproxy.cn,https://goproxy.io,direct" - ) + # vendor 目录存在,显示信息 + VENDOR_COUNT=$(find "$SOURCE_DIR/vendor" -type d -mindepth 2 2>/dev/null | wc -l | tr -d '\n' || echo "0") + VENDOR_COUNT=${VENDOR_COUNT:-0} + echo -e "${GREEN}✓ vendor 目录存在${NC}" + echo -e "${BLUE}vendor 目录包含 ${GREEN}${VENDOR_COUNT}${NC} 个依赖包" + echo -e "${BLUE}编译时将使用 -mod=vendor 标志,无需网络连接${NC}" - # 测试并选择最快的 Go 代理(使用多个镜像作为备选) - GO_PROXY="" - for proxy_list in "${GO_PROXY_MIRRORS[@]}"; do - # 取第一个镜像进行测试 - first_proxy=$(echo "$proxy_list" | cut -d',' -f1) - echo -n " 测试代理链: ${first_proxy}... " - - # 使用 Go 代理的特定端点进行测试(访问一个已知的模块信息) - # goproxy.cn 等代理服务需要访问 /{module}/@v/list 这样的端点 - # 这里测试访问 goproxy.cn 的根路径或使用 go env 测试 - TEST_URL="${first_proxy}" - - # 尝试多种测试方法 - PROXY_AVAILABLE=false - - # 方法1: 直接访问根路径 - if curl -sf --connect-timeout 3 --max-time 5 "${TEST_URL}" > /dev/null 2>&1; then - PROXY_AVAILABLE=true - # 方法2: 访问 goproxy.cn 的统计页面(如果存在) - elif curl -sf --connect-timeout 3 --max-time 5 "${TEST_URL}/statistics" > /dev/null 2>&1; then - PROXY_AVAILABLE=true - # 方法3: 使用 go env 测试(如果 Go 已安装) - elif command -v go > /dev/null 2>&1; then - # 临时设置 GOPROXY 并测试 - if GOPROXY="${first_proxy},direct" go env GOPROXY > /dev/null 2>&1; then - PROXY_AVAILABLE=true - fi - # 方法4: 尝试访问一个已知模块的列表端点 - elif curl -sf --connect-timeout 3 --max-time 5 "${TEST_URL}/github.com/gin-gonic/gin/@v/list" > /dev/null 2>&1; then - PROXY_AVAILABLE=true - fi - - if [ "$PROXY_AVAILABLE" = true ]; then - GO_PROXY="$proxy_list" - echo -e "${GREEN}可用${NC}" - break - else - echo -e "${RED}不可用${NC}" - fi - done - - # 如果所有镜像都不可用,使用 direct 模式(直接从源码仓库下载) - if [ -z "$GO_PROXY" ]; then - GO_PROXY="direct" - echo -e "${YELLOW}⚠ 所有国内镜像不可用,使用 direct 模式(直接从 GitHub/GitLab 等下载)${NC}" - echo -e "${YELLOW}⚠ 注意: direct 模式可能较慢,建议检查网络连接${NC}" - else - echo -e "${GREEN}✓ 使用 Go 代理链: ${GO_PROXY}${NC}" - echo -e "${BLUE}说明: Go 会按顺序尝试代理列表中的镜像,最后使用 direct 模式${NC}" - echo -e "${BLUE}注意: 已禁用 GOSUMDB,避免连接 proxy.golang.org${NC}" - fi - - # 下载依赖(使用 sudo 以 root 用户执行,确保 PATH 包含 Go,并设置 GOPROXY) - echo -e "${BLUE}下载 Go 依赖...${NC}" - echo -e "${BLUE}使用代理: ${GO_PROXY}${NC}" - - # 构建包含 Go PATH 和 GOPROXY 的环境变量 + # 构建包含 Go PATH 的环境变量 GO_PATH_ENV="PATH=\$PATH:/usr/local/go/bin" if [ -d "/usr/local/go/bin" ]; then GO_PATH_ENV="PATH=/usr/local/go/bin:\$PATH" fi - # 禁用 GOSUMDB 以避免连接 proxy.golang.org(在中国大陆通常无法访问) - # 如果必须启用校验和,可以使用 GOSUMDB=sum.golang.google.cn,但可能仍有问题 - # 如果配置了 GitHub 代理,添加到环境变量中 - if [ -n "$GITHUB_PROXY" ]; then - GO_ENV="$GO_PATH_ENV GOPROXY=${GO_PROXY} GOSUMDB=off GOTIMEOUT=60 GONOPROXY= GONOSUMDB= GOPRIVATE=* HTTP_PROXY=${GITHUB_PROXY}/ HTTPS_PROXY=${GITHUB_PROXY}/ http_proxy=${GITHUB_PROXY}/ https_proxy=${GITHUB_PROXY}/" - else - GO_ENV="$GO_PATH_ENV GOPROXY=${GO_PROXY} GOSUMDB=off GOTIMEOUT=60 GONOPROXY= GONOSUMDB= GOPRIVATE=*" - fi - - # 使用 go env -w 永久设置环境变量(避免被其他配置覆盖) - echo -e "${BLUE}永久设置 Go 环境变量(避免连接 proxy.golang.org)...${NC}" - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=${GO_PROXY}" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOSUMDB=off" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPRIVATE=*" 2>/dev/null || true - - # 显示当前 Go 环境信息(验证设置是否生效) - echo -e "${BLUE}Go 环境信息:${NC}" - echo -e "${BLUE} 设置的 GOPROXY=${GO_PROXY}${NC}" - echo -e "${BLUE} 设置的 GOSUMDB=off (已禁用,避免连接 proxy.golang.org)${NC}" - echo -e "${BLUE} 实际生效的环境变量:${NC}" - sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && go env GOPROXY GOSUMDB GOPRIVATE" || true - echo "" - - # 验证是否仍然会连接 proxy.golang.org - ACTUAL_GOPROXY=$(sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && go env GOPROXY" 2>/dev/null || echo "") - if echo "$ACTUAL_GOPROXY" | grep -q "proxy.golang.org"; then - echo -e "${RED}⚠ 警告: 检测到 GOPROXY 仍包含 proxy.golang.org${NC}" - echo -e "${YELLOW}正在强制移除 proxy.golang.org...${NC}" - CLEAN_PROXY=$(echo "$ACTUAL_GOPROXY" | sed 's|https://proxy.golang.org,||g' | sed 's|,https://proxy.golang.org||g' | sed 's|https://proxy.golang.org||g') - GO_PROXY="$CLEAN_PROXY" - GO_ENV="$GO_PATH_ENV GOPROXY=${GO_PROXY} GOSUMDB=off GOTIMEOUT=60 GONOPROXY= GONOSUMDB= GOPRIVATE=*" - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=${GO_PROXY}" 2>/dev/null || true - echo -e "${GREEN}✓ 已更新 GOPROXY: ${GO_PROXY}${NC}" - fi - - # 先尝试整理依赖(显示详细信息) - echo -e "${BLUE}整理 Go 模块依赖...${NC}" - # 再次确认环境变量(防止被覆盖) - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=${GO_PROXY}" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOSUMDB=off" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPRIVATE=*" 2>/dev/null || true - - if ! sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && go mod tidy -v" 2>&1; then - echo -e "${YELLOW}⚠ go mod tidy 失败,继续尝试下载依赖...${NC}" - # 检查错误日志中是否包含 proxy.golang.org - TIDY_LOG=$(sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && go mod tidy -v" 2>&1 || true) - if echo "$TIDY_LOG" | grep -q "proxy.golang.org"; then - echo -e "${RED}错误: 检测到仍尝试连接 proxy.golang.org${NC}" - echo -e "${YELLOW}尝试清理 Go 模块缓存并重新设置...${NC}" - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go clean -modcache" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=${GO_PROXY}" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOSUMDB=off" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPRIVATE=*" 2>/dev/null || true - fi - fi - - # 下载依赖(显示详细进度和速度) - echo -e "${BLUE}开始下载 Go 依赖包(这可能需要一些时间)...${NC}" - echo -e "${YELLOW}提示: 如果下载速度慢,请检查网络连接和代理设置${NC}" - echo "" - - # 设置更长的超时时间和启用详细输出 - DOWNLOAD_START_TIME=$(date +%s) - DOWNLOAD_LOG="/tmp/go_download_$$.log" - DOWNLOAD_PROGRESS_LOG="/tmp/go_progress_$$.log" - - # 在下载前再次确认环境变量设置(强制所有包都通过代理) - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=${GO_PROXY}" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOSUMDB=off" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GONOPROXY=" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GONOSUMDB=" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPRIVATE=*" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOTIMEOUT=60" 2>/dev/null || true - - # 使用命名管道来实时监控输出 - PIPE_FILE="/tmp/go_download_pipe_$$" - mkfifo "$PIPE_FILE" 2>/dev/null || true - - # 后台进程显示实时进度 - ( - DOWNLOADED_COUNT=0 - LAST_COUNT=0 - LAST_PACKAGE="" - PACKAGES=() - - # 从管道读取输出并实时显示 - while IFS= read -r line || [ -n "$line" ]; do - # 检查是否结束 - if [ -f "${DOWNLOAD_PROGRESS_LOG}.done" ]; then - break - fi - - # 检测下载消息 - if echo "$line" | grep -q "go: downloading"; then - DOWNLOADED_COUNT=$((DOWNLOADED_COUNT + 1)) - CURRENT_TIME=$(date +%s) - ELAPSED=$((CURRENT_TIME - DOWNLOAD_START_TIME)) - - # 提取包名 - PACKAGE_NAME=$(echo "$line" | sed 's/go: downloading //' | cut -d' ' -f1) - if [ -n "$PACKAGE_NAME" ] && [ "$PACKAGE_NAME" != "$LAST_PACKAGE" ]; then - PACKAGES+=("$PACKAGE_NAME") - LAST_PACKAGE=$PACKAGE_NAME - - # 计算速度 - if [ "$ELAPSED" -gt 0 ]; then - SPEED=$(echo "scale=2; $DOWNLOADED_COUNT / $ELAPSED" | bc 2>/dev/null || echo "0") - else - SPEED="0" - fi - - # 显示进度(使用 \r 在同一行更新) - echo -ne "\r${BLUE}进度: 已下载 ${GREEN}${DOWNLOADED_COUNT}${NC} 个包 | 耗时: ${ELAPSED}秒 | 速度: ${GREEN}${SPEED}${NC} 包/秒 | 当前: ${GREEN}${PACKAGE_NAME}${NC} " - fi - fi - done < "$PIPE_FILE" & - - # 等待主进程结束 - while [ ! -f "${DOWNLOAD_PROGRESS_LOG}.done" ]; do - sleep 0.5 - done - ) & - PROGRESS_PID=$! - - # 使用 -x 标志下载,显示详细输出,同时写入日志和管道 - # 设置较短的超时时间,避免长时间卡住 - echo -e "${BLUE}开始下载(超时时间:300秒)...${NC}" - - # 确保环境变量中包含代理设置 - if [ -n "$GITHUB_PROXY" ]; then - GO_ENV="$GO_ENV HTTP_PROXY=${GITHUB_PROXY}/ HTTPS_PROXY=${GITHUB_PROXY}/ http_proxy=${GITHUB_PROXY}/ https_proxy=${GITHUB_PROXY}/" - fi - - # 使用 timeout 命令设置总超时时间 - if timeout 300 sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && go mod download -x" 2>&1 | tee "$DOWNLOAD_LOG" "$PIPE_FILE"; then - # 停止进度显示进程 - touch "${DOWNLOAD_PROGRESS_LOG}.done" - sleep 2 - kill "$PROGRESS_PID" 2>/dev/null || true - wait "$PROGRESS_PID" 2>/dev/null || true - - # 清理管道文件 - rm -f "$PIPE_FILE" 2>/dev/null || true - - DOWNLOAD_END_TIME=$(date +%s) - DOWNLOAD_DURATION=$((DOWNLOAD_END_TIME - DOWNLOAD_START_TIME)) - - # 统计下载信息(从输出中统计,去除换行符) - TOTAL_PACKAGES=$(grep -c "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - SUCCESS_COUNT=$(grep -c "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - - # 确保是数字 - TOTAL_PACKAGES=${TOTAL_PACKAGES:-0} - SUCCESS_COUNT=${SUCCESS_COUNT:-0} - - echo "" - echo -e "${GREEN}✓ 依赖下载完成${NC}" - echo -e "${BLUE}下载统计:${NC}" - echo -e " 总包数: ${GREEN}${TOTAL_PACKAGES}${NC}" - echo -e " 成功下载: ${GREEN}${SUCCESS_COUNT}${NC}" - echo -e " 总耗时: ${GREEN}${DOWNLOAD_DURATION}${NC}秒" - - if [ "$DOWNLOAD_DURATION" -gt 0 ] && [ "$SUCCESS_COUNT" -gt 0 ] 2>/dev/null; then - AVG_SPEED=$(echo "scale=2; $SUCCESS_COUNT / $DOWNLOAD_DURATION" | bc 2>/dev/null || echo "0") - echo -e " 平均速度: ${GREEN}${AVG_SPEED}${NC} 包/秒" - fi - - # 显示最后下载的几个包 - echo -e "${BLUE}最后下载的包:${NC}" - grep "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null | tail -10 | sed 's/go: downloading \([^ ]*\).*/ ✓ \1/' | while IFS= read -r line; do - echo "$line" - done || true - else - # 停止进度显示进程 - touch "${DOWNLOAD_PROGRESS_LOG}.done" - sleep 2 - kill "$PROGRESS_PID" 2>/dev/null || true - wait "$PROGRESS_PID" 2>/dev/null || true - - # 清理管道文件 - rm -f "$PIPE_FILE" 2>/dev/null || true - - DOWNLOAD_EXIT_CODE=${DOWNLOAD_EXIT_CODE:-$?} - DOWNLOAD_END_TIME=$(date +%s) - DOWNLOAD_DURATION=$((DOWNLOAD_END_TIME - DOWNLOAD_START_TIME)) - - # 统计已下载的包(去除换行符) - DOWNLOADED_COUNT=$(grep -c "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - DOWNLOADED_COUNT=${DOWNLOADED_COUNT:-0} - - if [ "$DOWNLOAD_EXIT_CODE" = "124" ]; then - echo "" - echo -e "${YELLOW}⚠ 下载超时 (${DOWNLOAD_DURATION}秒)${NC}" - echo -e "${BLUE}已下载: ${GREEN}${DOWNLOADED_COUNT}${NC} 个包" - echo -e "${YELLOW}继续尝试编译,如果失败请检查网络连接${NC}" - else - echo "" - echo -e "${YELLOW}⚠ 使用国内镜像下载失败 (耗时: ${DOWNLOAD_DURATION}秒,退出码: ${DOWNLOAD_EXIT_CODE})${NC}" - echo -e "${BLUE}已下载: ${GREEN}${DOWNLOADED_COUNT}${NC} 个包" - echo -e "${YELLOW}最后30行日志:${NC}" - tail -30 "$DOWNLOAD_LOG" 2>/dev/null || true - echo "" - echo -e "${YELLOW}尝试使用 direct 模式(直接从 GitHub/GitLab 等下载)...${NC}" - # 如果失败,尝试使用 direct 模式,直接从源码仓库下载 - # 注意:不使用 proxy.golang.org,因为在中国大陆无法访问 - GO_ENV="$GO_PATH_ENV GOPROXY=direct GOSUMDB=off GOTIMEOUT=60 GONOPROXY= GONOSUMDB= GOPRIVATE=*" - - # 如果配置了 GitHub 代理,添加到环境变量 - if [ -n "$GITHUB_PROXY" ]; then - GO_ENV="$GO_ENV HTTP_PROXY=${GITHUB_PROXY}/ HTTPS_PROXY=${GITHUB_PROXY}/ http_proxy=${GITHUB_PROXY}/ https_proxy=${GITHUB_PROXY}/" - fi - - # 重新设置环境变量 - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPROXY=direct" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOSUMDB=off" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GONOPROXY=" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GONOSUMDB=" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOPRIVATE=*" 2>/dev/null || true - sudo bash -c "cd '$SOURCE_DIR' && $GO_PATH_ENV && go env -w GOTIMEOUT=60" 2>/dev/null || true - - # 重新启动进度显示 - ( - DOWNLOADED_COUNT=0 - LAST_UPDATE_TIME=$(date +%s) - LAST_COUNT=0 - - while [ ! -f "$DOWNLOAD_PROGRESS_LOG.done2" ]; do - sleep 1 - - CURRENT_COUNT=$(grep -c "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null || echo "0") - - if [ "$CURRENT_COUNT" -gt "$LAST_COUNT" ]; then - DOWNLOADED_COUNT=$CURRENT_COUNT - CURRENT_TIME=$(date +%s) - ELAPSED=$((CURRENT_TIME - DOWNLOAD_START_TIME)) - - if [ "$ELAPSED" -gt 0 ]; then - SPEED=$(echo "scale=2; $DOWNLOADED_COUNT / $ELAPSED" | bc 2>/dev/null || echo "0") - echo -ne "\r${BLUE}进度: 已下载 ${GREEN}${DOWNLOADED_COUNT}${NC} 个包 | 耗时: ${ELAPSED}秒 | 速度: ${GREEN}${SPEED}${NC} 包/秒" - fi - - LAST_COUNT=$CURRENT_COUNT - fi - - CURRENT_PACKAGE=$(grep "go: downloading" "$DOWNLOAD_LOG" | tail -1 | sed 's/go: downloading //' | cut -d' ' -f1) - if [ -n "$CURRENT_PACKAGE" ] && [ "$CURRENT_PACKAGE" != "$LAST_PACKAGE" ]; then - echo "" - echo -e "${BLUE} → 正在下载: ${GREEN}${CURRENT_PACKAGE}${NC}" - LAST_PACKAGE=$CURRENT_PACKAGE - fi - done - ) & - PROGRESS_PID2=$! - - # 重新创建管道 - rm -f "$PIPE_FILE" 2>/dev/null || true - mkfifo "$PIPE_FILE" 2>/dev/null || true - - # 重新启动进度显示 - ( - DOWNLOADED_COUNT=0 - LAST_COUNT=0 - LAST_PACKAGE="" - - while IFS= read -r line || [ -n "$line" ]; do - if [ -f "${DOWNLOAD_PROGRESS_LOG}.done2" ]; then - break - fi - - if echo "$line" | grep -q "go: downloading"; then - DOWNLOADED_COUNT=$((DOWNLOADED_COUNT + 1)) - CURRENT_TIME=$(date +%s) - ELAPSED=$((CURRENT_TIME - DOWNLOAD_START_TIME)) - - PACKAGE_NAME=$(echo "$line" | sed 's/go: downloading //' | cut -d' ' -f1) - if [ -n "$PACKAGE_NAME" ] && [ "$PACKAGE_NAME" != "$LAST_PACKAGE" ]; then - LAST_PACKAGE=$PACKAGE_NAME - - if [ "$ELAPSED" -gt 0 ]; then - SPEED=$(echo "scale=2; $DOWNLOADED_COUNT / $ELAPSED" | bc 2>/dev/null || echo "0") - else - SPEED="0" - fi - - echo -ne "\r${BLUE}进度: 已下载 ${GREEN}${DOWNLOADED_COUNT}${NC} 个包 | 耗时: ${ELAPSED}秒 | 速度: ${GREEN}${SPEED}${NC} 包/秒 | 当前: ${GREEN}${PACKAGE_NAME}${NC} " - fi - fi - done < "$PIPE_FILE" & - - while [ ! -f "${DOWNLOAD_PROGRESS_LOG}.done2" ]; do - sleep 0.5 - done - ) & - PROGRESS_PID2=$! - - DOWNLOAD_START_TIME=$(date +%s) - if sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && timeout 600 go mod download -x" 2>&1 | tee "$DOWNLOAD_LOG" "$PIPE_FILE"; then - # 停止进度显示进程 - touch "${DOWNLOAD_PROGRESS_LOG}.done2" - sleep 2 - kill "$PROGRESS_PID2" 2>/dev/null || true - wait "$PROGRESS_PID2" 2>/dev/null || true - rm -f "$PIPE_FILE" 2>/dev/null || true - - DOWNLOAD_END_TIME=$(date +%s) - DOWNLOAD_DURATION=$((DOWNLOAD_END_TIME - DOWNLOAD_START_TIME)) - - # 统计下载信息(去除换行符) - TOTAL_PACKAGES=$(grep -c '"Path":' "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - SUCCESS_COUNT=$(grep -c '"Version":' "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - - # 如果没有 JSON 格式,尝试从普通输出统计 - if [ "$TOTAL_PACKAGES" = "0" ] || [ -z "$TOTAL_PACKAGES" ]; then - TOTAL_PACKAGES=$(grep -c "go: downloading" "$DOWNLOAD_LOG" 2>/dev/null | tr -d '\n' || echo "0") - SUCCESS_COUNT=$TOTAL_PACKAGES - fi - - # 确保是数字 - TOTAL_PACKAGES=${TOTAL_PACKAGES:-0} - SUCCESS_COUNT=${SUCCESS_COUNT:-0} - - echo "" - echo -e "${GREEN}✓ 依赖下载完成${NC}" - echo -e "${BLUE}下载统计:${NC}" - echo -e " 总包数: ${GREEN}${TOTAL_PACKAGES}${NC}" - echo -e " 成功下载: ${GREEN}${SUCCESS_COUNT}${NC}" - echo -e " 总耗时: ${GREEN}${DOWNLOAD_DURATION}${NC}秒" - - if [ "$DOWNLOAD_DURATION" -gt 0 ] && [ "$SUCCESS_COUNT" -gt 0 ] 2>/dev/null; then - AVG_SPEED=$(echo "scale=2; $SUCCESS_COUNT / $DOWNLOAD_DURATION" | bc 2>/dev/null || echo "0") - echo -e " 平均速度: ${GREEN}${AVG_SPEED}${NC} 包/秒" - fi - else - echo -e "${RED}下载依赖失败,最后100行日志:${NC}" - tail -100 "$DOWNLOAD_LOG" 2>/dev/null || true - rm -f "$DOWNLOAD_LOG" - show_build_alternatives - exit 1 - fi - fi - fi - - rm -f "$DOWNLOAD_LOG" 2>/dev/null || true + # 设置 Go 环境变量(仅包含 PATH,不使用代理) + GO_ENV="$GO_PATH_ENV" # 编译到临时文件(在用户有权限的目录),然后移动到目标位置 echo -e "${BLUE}编译二进制文件...${NC}" TEMP_BINARY=$(mktemp) BINARY_PATH="$SOURCE_DIR/agent" - # 使用 sudo 以 root 用户编译,直接输出到目标位置,确保 PATH 包含 Go,并设置 GOPROXY + # 使用 sudo 以 root 用户编译,直接输出到目标位置,强制使用 vendor echo -e "${BLUE}开始编译(架构: ${ARCH})...${NC}" - if sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && GOOS=linux GOARCH=${ARCH} CGO_ENABLED=0 go build -v -buildvcs=false -ldflags='-w -s' -o '$BINARY_PATH' ./cmd/agent" 2>&1 | tee /tmp/go_build.log; then + echo -e "${BLUE}使用 vendor 目录编译(无需网络连接)...${NC}" + + # 强制使用 vendor 模式编译 + BUILD_FLAGS="-mod=vendor -v -buildvcs=false -ldflags='-w -s'" + + if sudo bash -c "cd '$SOURCE_DIR' && $GO_ENV && GOOS=linux GOARCH=${ARCH} CGO_ENABLED=0 go build $BUILD_FLAGS -o '$BINARY_PATH' ./cmd/agent" 2>&1 | tee /tmp/go_build.log; then if [ -f "$BINARY_PATH" ] && [ -s "$BINARY_PATH" ]; then sudo chmod +x "$BINARY_PATH" BINARY_SIZE=$(du -h "$BINARY_PATH" | cut -f1) diff --git a/vendor.sh b/vendor.sh new file mode 100755 index 0000000..ee38ce8 --- /dev/null +++ b/vendor.sh @@ -0,0 +1,220 @@ +#!/bin/bash + +# ============================================ +# LinkMaster Node Vendor 依赖打包脚本 +# 用途:将项目依赖下载到 vendor 目录,客户端克隆后可直接编译,无需网络 +# 使用方法: ./vendor.sh +# ============================================ + +set -e + +# 颜色输出 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' + +# 脚本目录 +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +cd "$SCRIPT_DIR" + +# 检查 Go 环境 +check_go() { + if ! command -v go > /dev/null 2>&1; then + echo -e "${RED}错误: 未找到 Go 环境${NC}" + echo -e "${YELLOW}请先安装 Go: https://golang.org/dl/${NC}" + exit 1 + fi + + GO_VERSION=$(go version 2>/dev/null | head -1) + echo -e "${GREEN}✓ 检测到 Go: ${GO_VERSION}${NC}" +} + +# 配置 Go 环境(海外网络,直接使用官方源) +setup_go_env() { + echo -e "${BLUE}配置 Go 环境(使用官方源)...${NC}" + + # 海外网络可以直接使用官方源,无需代理 + # 使用官方 Go 代理和校验和数据库 + export GOPROXY="https://proxy.golang.org,direct" + export GOSUMDB="sum.golang.org" + + # 使用 go env -w 永久设置 + go env -w GOPROXY="https://proxy.golang.org,direct" 2>/dev/null || true + go env -w GOSUMDB="sum.golang.org" 2>/dev/null || true + + echo -e "${GREEN}✓ Go 环境配置完成(使用官方源)${NC}" + echo -e "${BLUE} GOPROXY=https://proxy.golang.org,direct${NC}" + echo -e "${BLUE} GOSUMDB=sum.golang.org${NC}" +} + +# 下载依赖 +download_dependencies() { + echo -e "${BLUE}下载 Go 依赖包...${NC}" + + # 先整理依赖 + echo -e "${BLUE}整理 Go 模块依赖...${NC}" + if ! go mod tidy -v 2>&1; then + echo -e "${YELLOW}⚠ go mod tidy 失败,继续尝试下载依赖...${NC}" + fi + + # 下载依赖 + echo -e "${BLUE}下载所有依赖包(这可能需要一些时间)...${NC}" + DOWNLOAD_START_TIME=$(date +%s) + + if go mod download -x 2>&1; then + DOWNLOAD_END_TIME=$(date +%s) + DOWNLOAD_DURATION=$((DOWNLOAD_END_TIME - DOWNLOAD_START_TIME)) + echo -e "${GREEN}✓ 依赖下载完成 (耗时: ${DOWNLOAD_DURATION}秒)${NC}" + else + echo -e "${RED}✗ 依赖下载失败${NC}" + exit 1 + fi +} + +# 创建 vendor 目录 +create_vendor() { + echo -e "${BLUE}创建 vendor 目录(打包所有依赖)...${NC}" + + # 删除旧的 vendor 目录(如果存在) + if [ -d "vendor" ]; then + echo -e "${YELLOW}清理旧的 vendor 目录...${NC}" + rm -rf vendor + fi + + # 创建 vendor 目录 + if go mod vendor -v 2>&1; then + VENDOR_COUNT=$(find vendor -type d -mindepth 2 2>/dev/null | wc -l | tr -d '\n' || echo "0") + VENDOR_COUNT=${VENDOR_COUNT:-0} + + # 计算 vendor 目录大小 + VENDOR_SIZE=$(du -sh vendor 2>/dev/null | cut -f1 || echo "未知") + + echo -e "${GREEN}✓ vendor 目录创建成功${NC}" + echo -e "${BLUE}统计信息:${NC}" + echo -e " 依赖包数量: ${GREEN}${VENDOR_COUNT}${NC}" + echo -e " 目录大小: ${GREEN}${VENDOR_SIZE}${NC}" + else + echo -e "${RED}✗ vendor 创建失败${NC}" + exit 1 + fi +} + +# 更新 .gitignore +update_gitignore() { + echo -e "${BLUE}更新 .gitignore...${NC}" + + if [ ! -f ".gitignore" ]; then + echo -e "${BLUE}创建 .gitignore 文件...${NC}" + touch .gitignore + fi + + # 检查 .gitignore 是否忽略了 vendor + if grep -q "^vendor$" .gitignore 2>/dev/null || grep -q "^vendor/" .gitignore 2>/dev/null; then + echo -e "${YELLOW}⚠ 检测到 .gitignore 中忽略了 vendor 目录${NC}" + echo -e "${BLUE}正在更新 .gitignore,允许 vendor 目录被提交...${NC}" + # 移除 vendor 相关的忽略规则 + sed -i.bak '/^vendor$/d; /^vendor\//d' .gitignore 2>/dev/null || \ + sed -i '' '/^vendor$/d; /^vendor\//d' .gitignore 2>/dev/null || true + rm -f .gitignore.bak 2>/dev/null || true + echo -e "${GREEN}✓ 已更新 .gitignore${NC}" + else + echo -e "${GREEN}✓ .gitignore 配置正确${NC}" + fi +} + +# 添加到 Git(可选) +add_to_git() { + if [ -d ".git" ]; then + echo -e "${BLUE}将 vendor 目录添加到 Git...${NC}" + + # 检查是否有未提交的更改 + if git status --porcelain vendor 2>/dev/null | grep -q vendor; then + git add vendor/ 2>/dev/null || true + echo -e "${GREEN}✓ vendor 目录已添加到 Git 暂存区${NC}" + echo -e "${YELLOW}提示: 请运行 'git commit -m \"chore: add vendor dependencies\"' 提交 vendor 目录${NC}" + else + echo -e "${BLUE}vendor 目录已在 Git 中${NC}" + fi + else + echo -e "${YELLOW}⚠ 当前目录不是 Git 仓库,跳过 Git 操作${NC}" + fi +} + +# 显示进度显示 +show_progress() { + echo -e "${BLUE}正在下载依赖包,显示进度...${NC}" + + # 使用后台进程显示进度 + ( + DOWNLOADED_COUNT=0 + LAST_COUNT=0 + LAST_PACKAGE="" + START_TIME=$(date +%s) + + while true; do + sleep 1 + + # 从 go mod download 的输出中统计 + CURRENT_COUNT=$(ps aux | grep -c "[g]o mod download" || echo "0") + + # 检查进程是否还在运行 + if ! pgrep -f "go mod download" > /dev/null 2>&1; then + break + fi + + CURRENT_TIME=$(date +%s) + ELAPSED=$((CURRENT_TIME - START_TIME)) + + if [ "$ELAPSED" -gt 0 ]; then + echo -ne "\r${BLUE}进度: 下载中... | 耗时: ${ELAPSED}秒 " + fi + done + ) & + PROGRESS_PID=$! + + # 等待下载完成 + wait $PROGRESS_PID 2>/dev/null || true +} + +# 主函数 +main() { + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN} LinkMaster Node Vendor 依赖打包工具${NC}" + echo -e "${GREEN}========================================${NC}" + echo "" + + # 检查是否在项目根目录 + if [ ! -f "go.mod" ]; then + echo -e "${RED}错误: 未找到 go.mod 文件${NC}" + echo -e "${YELLOW}请在项目根目录运行此脚本${NC}" + exit 1 + fi + + check_go + setup_go_env + download_dependencies + create_vendor + update_gitignore + add_to_git + + echo "" + echo -e "${GREEN}========================================${NC}" + echo -e "${GREEN} ✓ Vendor 依赖打包完成!${NC}" + echo -e "${GREEN}========================================${NC}" + echo "" + echo -e "${BLUE}下一步操作:${NC}" + echo " 1. 检查 vendor 目录: ls -lh vendor/" + echo " 2. 提交到 Git: git add vendor/ && git commit -m \"chore: add vendor dependencies\"" + echo " 3. 推送到远程: git push" + echo "" + echo -e "${BLUE}客户端使用:${NC}" + echo " 客户端克隆项目后,可以使用以下命令编译(无需网络):" + echo " go build -mod=vendor -o agent ./cmd/agent" + echo "" +} + +# 执行主函数 +main +