配置gonode等

This commit is contained in:
vet
2026-04-13 13:10:38 +07:00
parent 84e0bf2e5f
commit 08dd783bd3

291
00-init-tools.sh Executable file
View File

@@ -0,0 +1,291 @@
#!/usr/bin/env bash
# =============================================================================
# 00-init-tools.sh — 安装并配置服务器基础工具环境
#
# 功能:
# 1. 安装 Go默认 1.22.5,可通过参数指定版本)
# 2. 配置 GOPROXY自动测速选最快节点
# 3. 安装 Node.js / npm前端依赖
# 4. 安装 Docker基础设施容器
# 5. 写入 /etc/profile.d/deploy-env.sh永久生效
#
# 用法:
# ./deploy-test/00-init-tools.sh # 安装全部
# ./deploy-test/00-init-tools.sh go # 只安装/配置 Go
# ./deploy-test/00-init-tools.sh node # 只安装 Node.js
# ./deploy-test/00-init-tools.sh docker # 只安装 Docker
# ./deploy-test/00-init-tools.sh goproxy # 只配置 GOPROXY
#
# 前置条件: root 或 sudo 权限Ubuntu/Debian 系统
#
# 下一步: ./deploy-test/01-init-env.sh
# =============================================================================
set -euo pipefail
source "$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/common.sh"
init_dirs
init_script_log
# ── 可调参数 ───────────────────────────────────────────────────────────────────
GO_VERSION="${GO_VERSION:-1.22.5}"
GO_ARCH="${GO_ARCH:-amd64}" # amd64 / arm64
NODE_VERSION="${NODE_VERSION:-20}" # Node.js LTS 大版本
PROFILE_FILE="/etc/profile.d/deploy-env.sh"
TARGET="${1:-all}"
header "步骤 0 — 初始化工具环境"
echo " 目标: ${TARGET} (Go=${GO_VERSION}, Node=${NODE_VERSION})"
# ──────────────────────────────────────────────────────────────────────────────
# 辅助函数
# ──────────────────────────────────────────────────────────────────────────────
# 检查命令是否存在(不触发 set -e
_has() { command -v "$1" &>/dev/null; }
# 追加到全局 profile幂等同一行不重复写
_append_profile() {
local line="$1"
grep -qxF "$line" "$PROFILE_FILE" 2>/dev/null || echo "$line" >> "$PROFILE_FILE"
}
# 测试 GOPROXY 节点延迟,返回 ms超时返回 9999
_probe_proxy() {
local url="${1%/}/github.com/gin-gonic/gin/@v/list"
local ms
ms=$(curl -s -o /dev/null -w "%{time_total}" --max-time 5 "$url" 2>/dev/null || echo "9.999")
echo "${ms/./}" | sed 's/^0*//' | awk '{printf "%d\n", $1 * 1000 / 1000 + 0}'
# 简单地把秒转毫秒并取整
python3 -c "print(int(float('${ms}') * 1000))" 2>/dev/null || echo 9999
}
# ──────────────────────────────────────────────────────────────────────────────
# 1. Go
# ──────────────────────────────────────────────────────────────────────────────
_install_go() {
step "安装 Go ${GO_VERSION} (linux/${GO_ARCH})"
local tarball="go${GO_VERSION}.linux-${GO_ARCH}.tar.gz"
local url="https://go.dev/dl/${tarball}"
local tmp="/tmp/${tarball}"
if _has go; then
local cur
cur=$(go version | awk '{print $3}' | sed 's/go//')
if [[ "$cur" == "$GO_VERSION" ]]; then
success " Go ${GO_VERSION} 已安装,跳过"
return 0
fi
warn " 当前 Go 版本 ${cur},将升级到 ${GO_VERSION}"
fi
info " 下载 ${url}"
curl -fL --progress-bar -o "$tmp" "$url" || {
# 备用镜像
warn " go.dev 下载失败,尝试备用镜像..."
curl -fL --progress-bar -o "$tmp" "https://golang.google.cn/dl/${tarball}" || {
error " 下载失败,请手动安装: https://go.dev/dl/"
return 1
}
}
info " 解压到 /usr/local/go"
rm -rf /usr/local/go
tar -C /usr/local -xzf "$tmp"
rm -f "$tmp"
# 写入 profile
[[ -f "$PROFILE_FILE" ]] || touch "$PROFILE_FILE"
_append_profile 'export PATH=$PATH:/usr/local/go/bin'
_append_profile 'export GOPATH=/root/go'
_append_profile 'export GOMODCACHE=/root/go/pkg/mod'
# 当前会话也生效
export PATH=$PATH:/usr/local/go/bin
export GOPATH=/root/go
export GOMODCACHE=/root/go/pkg/mod
success " Go $(go version | awk '{print $3}') 安装完成 → /usr/local/go/bin/go"
}
# ──────────────────────────────────────────────────────────────────────────────
# 2. GOPROXY — 自动选最快节点
# ──────────────────────────────────────────────────────────────────────────────
_config_goproxy() {
step "配置 GOPROXY自动测速"
if ! _has go; then
warn " go 未安装,跳过 GOPROXY 配置"
return 0
fi
declare -A PROXIES=(
["proxy.golang.org"]="https://proxy.golang.org"
["goproxy.cn"]="https://goproxy.cn"
["goproxy.io"]="https://goproxy.io"
)
local best_name="goproxy.io"
local best_ms=9999
info " 测速中..."
for name in "${!PROXIES[@]}"; do
local url="${PROXIES[$name]}"
local ms
ms=$(python3 -c "
import urllib.request, time, sys
try:
t = time.time()
urllib.request.urlopen('${url}/github.com/gin-gonic/gin/@v/list', timeout=5)
print(int((time.time()-t)*1000))
except:
print(9999)
" 2>/dev/null)
echo " ${name}: ${ms}ms"
if (( ms < best_ms )); then
best_ms=$ms
best_name=$name
best_url="${url}"
fi
done
# 构建代理列表:最快的放第一
local proxy_list="${best_url},https://proxy.golang.org,https://goproxy.cn,direct"
# 去重
proxy_list=$(echo "$proxy_list" | tr ',' '\n' | awk '!seen[$0]++' | tr '\n' ',' | sed 's/,$//')
go env -w GOPROXY="${proxy_list}"
go env -w GONOSUMDB="*"
go env -w GOFLAGS=""
# 同步写入 profilego env -w 已持久化到 GOENV这里写 profile 作为双保险)
_append_profile "export GOPROXY=${proxy_list}"
_append_profile 'export GONOSUMDB=*'
success " GOPROXY=${proxy_list}"
success " 最快节点: ${best_name} (${best_ms}ms)"
}
# ──────────────────────────────────────────────────────────────────────────────
# 3. Node.js
# ──────────────────────────────────────────────────────────────────────────────
_install_node() {
step "安装 Node.js ${NODE_VERSION}.x LTS"
if _has node; then
local cur
cur=$(node --version)
info " 当前 Node.js 版本: ${cur}"
# 检查大版本是否匹配
local major
major=$(echo "$cur" | sed 's/v//' | cut -d. -f1)
if (( major >= NODE_VERSION )); then
success " Node.js >= ${NODE_VERSION},跳过"
return 0
fi
warn " 版本过旧,将升级"
fi
if _has apt-get; then
info " 使用 NodeSource 安装 Node.js ${NODE_VERSION}.x"
curl -fsSL "https://deb.nodesource.com/setup_${NODE_VERSION}.x" | bash -
apt-get install -y nodejs
elif _has yum; then
curl -fsSL "https://rpm.nodesource.com/setup_${NODE_VERSION}.x" | bash -
yum install -y nodejs
else
warn " 未找到 apt-get/yum请手动安装 Node.js: https://nodejs.org/"
return 1
fi
# 安装常用全局包管理器
npm install -g pnpm yarn 2>/dev/null || true
_append_profile 'export PATH=$PATH:/usr/local/bin'
success " Node.js $(node --version)npm $(npm --version) 安装完成"
_has pnpm && success " pnpm $(pnpm --version)"
_has yarn && success " yarn $(yarn --version)"
}
# ──────────────────────────────────────────────────────────────────────────────
# 4. Docker
# ──────────────────────────────────────────────────────────────────────────────
_install_docker() {
step "安装 Docker"
if _has docker; then
success " Docker $(docker --version | awk '{print $3}' | tr -d ',') 已安装,跳过"
return 0
fi
if _has apt-get; then
info " 使用官方脚本安装 Docker..."
curl -fsSL https://get.docker.com | sh
elif _has yum; then
yum install -y docker
systemctl enable docker
else
warn " 未找到 apt-get/yum请手动安装 Docker: https://docs.docker.com/engine/install/"
return 1
fi
# 启动服务
systemctl start docker 2>/dev/null || service docker start 2>/dev/null || true
success " Docker $(docker --version | awk '{print $3}' | tr -d ',') 安装完成"
}
# ──────────────────────────────────────────────────────────────────────────────
# 执行
# ──────────────────────────────────────────────────────────────────────────────
case "$TARGET" in
go)
_install_go
_config_goproxy
;;
goproxy)
_config_goproxy
;;
node)
_install_node
;;
docker)
_install_docker
;;
all)
_install_go
_config_goproxy
_install_node
_install_docker
;;
*)
error "未知目标: $TARGET"
echo "用法: $0 [all|go|goproxy|node|docker]"
exit 1
;;
esac
# ──────────────────────────────────────────────────────────────────────────────
# 汇总
# ──────────────────────────────────────────────────────────────────────────────
echo ""
success "环境初始化完成!"
echo ""
echo -e "${BOLD}当前工具版本:${NC}"
_has go && echo " Go: $(go version | awk '{print $3, $4}')" || echo " Go: 未安装"
_has node && echo " Node: $(node --version)" || echo " Node: 未安装"
_has npm && echo " npm: $(npm --version)" || echo " npm: 未安装"
_has pnpm && echo " pnpm: $(pnpm --version)" || echo " pnpm: 未安装"
_has yarn && echo " yarn: $(yarn --version)" || echo " yarn: 未安装"
_has docker && echo " Docker: $(docker --version | awk '{print $3}' | tr -d ',')" || echo " Docker: 未安装"
echo ""
echo -e "${BOLD}GOPROXY 配置:${NC}"
_has go && go env GOPROXY || echo " (go 未安装)"
echo ""
echo -e "${YELLOW}注意: 新终端需执行以下命令使环境变量生效:${NC}"
echo -e " ${CYAN}source /etc/profile.d/deploy-env.sh${NC}"
echo -e " 或重新登录 SSH"
echo ""
echo -e "${BOLD}下一步:${NC}"
echo -e " ${CYAN}./deploy-test/01-init-env.sh${NC}"