配置gonode等
This commit is contained in:
291
00-init-tools.sh
Executable file
291
00-init-tools.sh
Executable 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=""
|
||||
|
||||
# 同步写入 profile(go 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}"
|
||||
Reference in New Issue
Block a user