#!/bin/bash # ================= 1. 全局设置 ================= set -e set -o pipefail set -u # ================= 2. 颜色与日志函数定义 ================= RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' # No Color log_info() { echo -e "${GREEN}[INFO]${NC} $1"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; } log_error() { echo -e "${RED}[ERROR]${NC} $1"; } log_step() { echo -e "${BLUE}[STEP]${NC} $1"; } log_success() { echo -e "${CYAN}[OK]${NC} $1"; } # 检查并安装sshpass|jq for pkg in sshpass jq; do if ! command -v $pkg &> /dev/null; then log_warn "未找到 $pkg,正在安装..." if command -v apt &> /dev/null; then sudo apt update >/dev/null 2>&1 && sudo apt install -y $pkg >/dev/null 2>&1 elif command -v yum &> /dev/null; then sudo yum install -y $pkg >/dev/null 2>&1 elif command -v dnf &> /dev/null; then sudo dnf install -y $pkg >/dev/null 2>&1 else log_error "请手动安装 $pkg" exit 1 fi log_success "$pkg 安装完成" fi done # ================= 3. 核心函数定义 ================= # 函数:获取远程文件的 SHA256 值 get_remote_sha256() { local SUM_URL=$1 local SUM_FILE=$(basename "$SUM_URL") local TEMP_SUM="/tmp/${SUM_FILE}.$$" # 使用进程ID避免冲突 # 下载校验和文件 (静默) if ! curl -sL -o "$TEMP_SUM" "$SUM_URL" 2>/dev/null; then log_error "无法下载校验和文件: $SUM_URL" rm -f "$TEMP_SUM" return 1 fi # 提取哈希值 local HASH=$(awk '{print $1}' "$TEMP_SUM") rm -f "$TEMP_SUM" if [ -z "$HASH" ]; then log_error "无法从校验和文件中解析哈希值" return 1 fi echo "$HASH" } # 函数:智能下载并校验 download_and_verify() { local BIN_URL=$1 local SUM_URL=$2 local FILENAME=$3 log_step " 正在检查 ${FILENAME} 的完整性..." # 1. 获取远程正确的 SHA256 local REMOTE_SHA REMOTE_SHA=$(get_remote_sha256 "$SUM_URL") local GET_HASH_STATUS=$? if [ $GET_HASH_STATUS -ne 0 ] || [ -z "$REMOTE_SHA" ]; then log_warn "⚠️ 无法获取远程哈希,将跳过版本比对,强制重新下载 ${FILENAME}..." REMOTE_SHA="" else log_info " 远程版本哈希: ${REMOTE_SHA:0:16}..." fi # 2. 检查本地文件是否存在且匹配 local NEED_DOWNLOAD=true if [ -f "$FILENAME" ]; then local LOCAL_SHA=$(sha256sum "$FILENAME" | awk '{print $1}') log_info " 本地版本哈希: ${LOCAL_SHA:0:16}..." if [ -n "$REMOTE_SHA" ] && [ "$LOCAL_SHA" == "$REMOTE_SHA" ]; then log_info "✅ ${FILENAME} 校验通过,无需下载。" NEED_DOWNLOAD=false else if [ -z "$REMOTE_SHA" ]; then log_warn "⚠️ ${FILENAME} 存在但无法验证远程版本,为确保一致性,准备更新..." else log_warn "⚠️ ${FILENAME} 哈希不匹配,准备更新..." fi fi else log_info " 本地文件不存在。" fi # 3. 如果需要下载 if [ "$NEED_DOWNLOAD" == true ]; then log_info " 正在下载 ${FILENAME} ..." # 使用 curl 下载,显示进度条 (-#), 跟随重定向 (-L) if ! curl -L# -o "$FILENAME" "$BIN_URL"; then log_error "❌ 下载 ${FILENAME} 失败!" rm -f "$FILENAME" # 清理可能损坏的部分文件 exit 1 fi # 4. 下载后再次校验 log_info " 正在校验下载文件的完整性..." local NEW_LOCAL_SHA=$(sha256sum "$FILENAME" | awk '{print $1}') if [ -n "$REMOTE_SHA" ] && [ "$NEW_LOCAL_SHA" != "$REMOTE_SHA" ]; then log_error "❌ 下载后的文件哈希校验失败!" log_error " 期望: $REMOTE_SHA" log_error " 实际: $NEW_LOCAL_SHA" log_error " 文件可能已损坏或被篡改,删除临时文件并退出。" rm -f "$FILENAME" exit 1 else log_info "✅ ${FILENAME} 下载成功且校验通过!" chmod +x "$FILENAME" log_info " 已添加执行权限。" fi fi } # ================= 4. 主执行流程 ================= echo "========================================" log_step " 阶段 0: 准备本地二进制文件 (MinIO & MC)" echo "========================================" # 定义资源 MINIO_BIN="minio" MC_BIN="mc" SERVICE_FILE="minio.service" # URL 定义 MINIO_URL="https://zhengyu1992.cn/file/software/minio/minio" MINIO_SUM_URL="https://zhengyu1992.cn/file/software/minio/minio.sha256sum" MC_URL="https://zhengyu1992.cn/file/software/minio/mc" MC_SUM_URL="https://zhengyu1992.cn/file/software/minio/mc.sha256sum" # 官方的minio文件 #MINIO_URL="https://dl.min.io/server/minio/release/linux-amd64/minio" #MINIO_SUM_URL="https://dl.min.io/server/minio/release/linux-amd64/minio.sha256sum" #MC_URL="https://dl.min.io/client/mc/release/linux-amd64/mc" #MC_SUM_URL="https://dl.min.io/client/mc/release/linux-amd64/mc.sha256sum" # 1. 下载 MinIO download_and_verify "$MINIO_URL" "$MINIO_SUM_URL" "$MINIO_BIN" # 2. 下载 MC 客户端 download_and_verify "$MC_URL" "$MC_SUM_URL" "$MC_BIN" cp mc /usr/local/bin/mc # 3. 处理 Service 文件 echo "----------------------------------------" if [ ! -f "$SERVICE_FILE" ]; then log_warn "⚠️ 本地缺少 ${SERVICE_FILE},正在生成默认配置..." cat > "$SERVICE_FILE" << 'EOF' [Unit] Description=MinIO Documentation=https://min-io.cn/docs/minio/linux/index.html Wants=network-online.target After=network-online.target AssertFileIsExecutable=/usr/local/bin/minio [Service] WorkingDirectory=/usr/local User=minio Group=minio ProtectProc=invisible EnvironmentFile=/etc/minio/minio.env ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/minio/minio.env\"; exit 1; fi" ExecStart=/usr/local/bin/minio server $MINIO_OPTS $MINIO_VOLUMES Restart=always LimitNOFILE=65536 TasksMax=infinity TimeoutStopSec=infinity SendSIGKILL=no [Install] WantedBy=multi-user.target EOF log_info "✅ ${SERVICE_FILE} 已生成。" else log_info "✅ ${SERVICE_FILE} 已存在,跳过生成。" fi echo "========================================" log_info " 本地文件准备就绪!" log_info " - 二进制文件: minio, mc" log_info " - 服务配置: minio.service" log_info " 下一步请运行: ./2.deploy_keys.sh" log_info " 现在可以运行部署脚本 2.deploy_keys.sh 进行密钥部署" echo "========================================" exit 0