#!/bin/bash set -e RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' log_info() { local message="[INFO] $1" echo -e "${BLUE}${message}${NC}" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$LOG_FILE" } log_success() { local message="[SUCCESS] $1" echo -e "${GREEN}${message}${NC}" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$LOG_FILE" } log_warning() { local message="[WARNING] $1" echo -e "${YELLOW}${message}${NC}" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$LOG_FILE" } log_error() { local message="[ERROR] $1" echo -e "${RED}${message}${NC}" echo "$(date '+%Y-%m-%d %H:%M:%S') $message" >> "$LOG_FILE" } # 配置变量 INSTALL_DIR="${1:-$(pwd)}" # 使用第一个参数作为安装目录,如果没有参数则使用当前目录 TEMP_DIR="/tmp/metrics-install-$$" VERSION_FILE="version.json" LOG_FILE="${INSTALL_DIR}/.install.log" # 安装日志文件 # 加载配置文件 load_config() { local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" local config_file="$script_dir/config.env" if [[ -f "$config_file" ]]; then log_info "加载配置文件: $config_file" # 导出配置文件中的环境变量 set -a # 自动导出所有变量 source "$config_file" set +a # 关闭自动导出 log_success "配置文件加载完成" else log_warning "配置文件不存在: $config_file,使用默认配置" fi } # 复制配置文件到安装目录 copy_config_files() { log_info "复制配置文件到安装目录..." local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" local source_config="$script_dir/../config/config.env" local target_config="$INSTALL_DIR/config.env" if [[ -f "$source_config" ]]; then # 检查源文件和目标文件是否是同一个文件 if [[ "$source_config" == "$target_config" ]]; then log_info "配置文件已在目标位置,跳过复制" log_success "配置文件已存在: $target_config" else if cp "$source_config" "$target_config"; then log_success "配置文件复制完成: $target_config" else log_error "配置文件复制失败" return 1 fi fi else log_warning "源配置文件不存在: $source_config" fi # 复制版本校验脚本 log_info "复制版本校验脚本到安装目录..." local target_check_version="$INSTALL_DIR/check_version.sh" # 检查目标文件是否已存在(从 artifact 包中解压出来的) if [[ -f "$target_check_version" ]]; then log_info "版本校验脚本已存在,设置执行权限..." chmod +x "$target_check_version" log_success "版本校验脚本权限设置完成: $target_check_version" else log_warning "版本校验脚本不存在: $target_check_version" log_info "请确保 check_version.sh 已包含在 artifact 包中" fi } check_root() { if [[ $EUID -ne 0 ]]; then log_error "此脚本需要 root 权限运行" log_info "请使用: sudo $0 [安装目录]" log_info "如果不指定安装目录,将使用当前目录: $(pwd)" exit 1 fi } # 检查系统要求 check_system() { log_info "检查系统要求..." # 检查操作系统 if [[ ! -f /etc/os-release ]]; then log_error "无法检测操作系统版本" exit 1 fi source /etc/os-release log_info "检测到操作系统: $NAME $VERSION" # 检查系统架构 arch=$(uname -m) log_info "系统架构: $arch" # 检查磁盘空间 available_space=$(df / | awk 'NR==2 {print $4}') if [[ $available_space -lt 10485760 ]]; then # 10GB in KB log_warning "可用磁盘空间不足 10GB,当前可用: $(($available_space / 1024 / 1024))GB" fi # 检查内存 total_mem=$(free -m | awk 'NR==2{print $2}') if [[ $total_mem -lt 4096 ]]; then # 4GB log_warning "系统内存不足 4GB,当前: ${total_mem}MB" fi } # 查找版本文件 find_version_file() { log_info "查找版本信息文件..." # 在当前目录查找 if [[ -f "$VERSION_FILE" ]]; then VERSION_FILE_PATH="$(pwd)/$VERSION_FILE" log_success "找到版本文件: $VERSION_FILE" return 0 fi # 在 artifact 目录查找 for version_dir in artifact/*/; do if [[ -f "${version_dir}${VERSION_FILE}" ]]; then VERSION_FILE_PATH="$(cd "$(dirname "${version_dir}${VERSION_FILE}")" && pwd)/$(basename "${version_dir}${VERSION_FILE}")" log_success "找到版本文件: $VERSION_FILE_PATH" return 0 fi done log_error "未找到版本信息文件 $VERSION_FILE" exit 1 } # 解析版本信息 parse_version_info() { log_info "解析版本信息..." if [[ ! -f "$VERSION_FILE_PATH" ]]; then log_error "版本文件不存在: $VERSION_FILE_PATH" exit 1 fi # 使用 jq 解析 JSON(如果可用) if command -v jq &> /dev/null; then # 验证JSON文件格式 if ! jq empty "$VERSION_FILE_PATH" 2>/dev/null; then log_error "JSON文件格式错误,请检查 $VERSION_FILE_PATH" exit 1 fi VERSION=$(jq -r '.version' "$VERSION_FILE_PATH") BUILD_TIME=$(jq -r '.build_time' "$VERSION_FILE_PATH") # 解析 artifact_list if jq -e '.artifact_list' "$VERSION_FILE_PATH" > /dev/null 2>&1; then jq -r '.artifact_list | to_entries[] | "\(.key):\(.value)"' "$VERSION_FILE_PATH" > "$TEMP_DIR/components.txt" else log_error "version.json 中缺少 artifact_list 字段" exit 1 fi # 解析 checksums if jq -e '.checksums' "$VERSION_FILE_PATH" > /dev/null 2>&1; then jq -r '.checksums | to_entries[] | "\(.key):\(.value)"' "$VERSION_FILE_PATH" > "$TEMP_DIR/checksums.txt" else log_error "version.json 中缺少 checksums 字段" exit 1 fi # 解析 install_order(现在包含完整的文件名) if jq -e '.install_order' "$VERSION_FILE_PATH" > /dev/null 2>&1; then jq -r '.install_order[]' "$VERSION_FILE_PATH" > "$TEMP_DIR/install_order.txt" else log_error "version.json 中缺少 install_order 字段" exit 1 fi else log_warning "jq 未安装,使用简单的 JSON 解析" # 简单的 JSON 解析 VERSION=$(grep '"version"' "$VERSION_FILE_PATH" | sed 's/.*"version": *"\([^"]*\)".*/\1/') BUILD_TIME=$(grep '"build_time"' "$VERSION_FILE_PATH" | sed 's/.*"build_time": *"\([^"]*\)".*/\1/') # 解析 artifact_list(跳过字段名本身) grep -A 100 '"artifact_list"' "$VERSION_FILE_PATH" | grep -v '"artifact_list"' | grep -E '^\s*"[^"]+":\s*"[^"]+"' | while read line; do component=$(echo "$line" | sed 's/.*"\([^"]*\)":\s*"[^"]*".*/\1/') version=$(echo "$line" | sed 's/.*"[^"]*":\s*"\([^"]*\)".*/\1/') echo "$component:$version" >> "$TEMP_DIR/components.txt" done # 解析 checksums(跳过字段名本身) grep -A 100 '"checksums"' "$VERSION_FILE_PATH" | grep -v '"checksums"' | grep -E '^\s*"[^"]+":\s*"[^"]+"' | while read line; do component=$(echo "$line" | sed 's/.*"\([^"]*\)":\s*"[^"]*".*/\1/') checksum=$(echo "$line" | sed 's/.*"[^"]*":\s*"\([^"]*\)".*/\1/') echo "$component:$checksum" >> "$TEMP_DIR/checksums.txt" done # 解析 install_order(跳过字段名本身,只取数组元素) grep -A 100 '"install_order"' "$VERSION_FILE_PATH" | grep -v '"install_order"' | grep -E '^\s*"[^"]+"' | while read line; do component=$(echo "$line" | sed 's/.*"\([^"]*\)".*/\1/') echo "$component" >> "$TEMP_DIR/install_order.txt" done # 验证解析结果 if [[ ! -f "$TEMP_DIR/components.txt" || ! -s "$TEMP_DIR/components.txt" ]]; then log_error "无法解析 artifact_list,请检查 version.json 格式" exit 1 fi if [[ ! -f "$TEMP_DIR/checksums.txt" || ! -s "$TEMP_DIR/checksums.txt" ]]; then log_error "无法解析 checksums,请检查 version.json 格式" exit 1 fi if [[ ! -f "$TEMP_DIR/install_order.txt" || ! -s "$TEMP_DIR/install_order.txt" ]]; then log_error "无法解析 install_order,请检查 version.json 格式" exit 1 fi fi log_success "版本信息解析完成" log_info " 版本: $VERSION" log_info " 构建时间: $BUILD_TIME" component_count=0 if [[ -f "$TEMP_DIR/components.txt" ]]; then component_count=$(wc -l < "$TEMP_DIR/components.txt") log_info " 组件数量: $component_count" log_info " 组件列表:" while IFS= read -r line; do component=$(echo "$line" | cut -d':' -f1) version=$(echo "$line" | cut -d':' -f2) log_info " - $component v$version" done < "$TEMP_DIR/components.txt" else log_error "components.txt 文件不存在" exit 1 fi } # 验证文件完整性 verify_checksums() { log_info "验证文件完整性..." artifact_dir=$(dirname "$VERSION_FILE_PATH") log_info "Artifact 目录: $artifact_dir" failed_verification=0 # 尝试解析 version.json 中的 install_order,用于锁定精确文件名,避免同一目录下多份历史 tar 产生歧义 local order_file="$TEMP_DIR/install_order.txt" if [[ -f "$TEMP_DIR/checksums.txt" ]]; then while IFS= read -r line; do component=$(echo "$line" | cut -d':' -f1) expected_checksum=$(echo "$line" | cut -d':' -f2-) # 优先从 install_order 中推导精确文件名 actual_file="" if [[ -f "$order_file" ]]; then while IFS= read -r fname; do if [[ "$fname" == ${component}-*.tar.gz && -f "$artifact_dir/$fname" ]]; then actual_file="$artifact_dir/$fname" break fi done < "$order_file" fi # 回退:按前缀匹配首个(不推荐,但保持兼容) if [[ -z "$actual_file" ]]; then for file in "$artifact_dir/${component}-"*.tar.gz; do if [[ -f "$file" ]]; then actual_file="$file" break fi done fi if [[ -z "$actual_file" ]]; then log_error "找不到组件文件: $component" failed_verification=1 continue fi # 计算实际校验和 actual_checksum="sha256:$(sha256sum "$actual_file" | cut -d' ' -f1)" if [[ "$actual_checksum" == "$expected_checksum" ]]; then log_success " $component: 校验通过" else log_error " $component: 校验失败" log_error " 期望: $expected_checksum" log_error " 实际: $actual_checksum" failed_verification=1 fi done < "$TEMP_DIR/checksums.txt" fi if [[ $failed_verification -eq 1 ]]; then log_error "文件完整性验证失败" exit 1 fi log_success "所有文件校验通过" } # 创建安装目录 create_install_dirs() { log_info "创建安装目录..." mkdir -p "$INSTALL_DIR" mkdir -p "$TEMP_DIR" log_success "安装目录创建完成: $INSTALL_DIR" } # 获取系统版本 get_system_version() { if [[ ! -f /etc/os-release ]]; then log_error "无法检测操作系统版本" return 1 fi source /etc/os-release # 提取主版本号 case "$VERSION_ID" in "20.04") echo "ubuntu20" ;; "22.04") echo "ubuntu22" ;; *) log_warning "未识别的Ubuntu版本: $VERSION_ID,尝试使用ubuntu22" echo "ubuntu22" ;; esac } # 安装系统依赖包 install_system_deps() { log_info "开始安装系统依赖包(离线模式)..." local artifact_dir artifact_dir=$(dirname "$VERSION_FILE_PATH") local deps_dir="$artifact_dir/deps" local system_version system_version=$(get_system_version) local version_deps_dir="$deps_dir/$system_version" if [[ ! -d "$version_deps_dir" ]]; then log_warning "未找到 $system_version 版本的依赖目录: $version_deps_dir,跳过安装" return 0 fi log_info "找到系统版本依赖目录: $version_deps_dir" local deps_temp_dir="/tmp/argus_deps" mkdir -p "$deps_temp_dir" rm -rf "$deps_temp_dir"/* local FAILED_DEPS=() local CORE_DEPS=(jq cron curl) # 核心依赖列表 # 遍历每个 tar.gz for tar_file in "$version_deps_dir"/*.tar.gz; do [[ -f "$tar_file" ]] || continue local tar_basename tar_basename=$(basename "$tar_file") log_info "处理依赖包: $tar_basename" local extract_dir="$deps_temp_dir/${tar_basename%.tar.gz}" mkdir -p "$extract_dir" if tar -xzf "$tar_file" -C "$extract_dir"; then log_success " $tar_basename 解压完成" else log_error " $tar_basename 解压失败" FAILED_DEPS+=("$tar_basename") continue fi # 递归查找所有 deb 文件,一次性安装 mapfile -t deb_files < <(find "$extract_dir" -type f -name "*.deb") if [[ ${#deb_files[@]} -eq 0 ]]; then log_warning " 没有找到 deb 包,跳过" continue fi log_info " 安装 ${#deb_files[@]} 个 deb 包..." if dpkg -i "${deb_files[@]}" &>/tmp/dpkg_install.log; then log_success " 所有 deb 包安装成功" else dpkg --configure -a || true if dpkg -l | grep -q '^ii'; then log_success " dpkg --configure 修复后安装成功" else log_error " 部分 deb 包安装失败,请手动安装" for deb in "${deb_files[@]}"; do pkg_name=$(dpkg-deb -f "$deb" Package 2>/dev/null || true) FAILED_DEPS+=("${pkg_name:-$deb}") done fi fi done # 启动 cron 服务或其它必要服务 start_cron_service # 检查核心依赖是否都已安装 local missing_core=() for dep in "${CORE_DEPS[@]}"; do if ! dpkg -s "$dep" &>/dev/null; then missing_core+=("$dep") fi done if [[ ${#missing_core[@]} -gt 0 ]]; then log_error "核心依赖安装失败,请手动安装以下组件:" for d in "${missing_core[@]}"; do echo " - $d" done exit 1 fi # 最终处理其他安装失败的包 if [[ ${#FAILED_DEPS[@]} -gt 0 ]]; then log_error "以下系统依赖安装失败,请手动安装后重试:" for f in "${FAILED_DEPS[@]}"; do echo " - $f" done exit 1 fi log_success "系统依赖安装完成,全部就绪" } # 启动 cron 服务 start_cron_service() { log_info "检查并启动 cron 服务..." # 检查 cron 是否已经在运行 if pgrep -x "cron" > /dev/null; then log_success "cron 服务已在运行" return 0 fi # 检查 /usr/sbin/cron 是否存在 if [[ ! -f "/usr/sbin/cron" ]]; then log_warning "cron 可执行文件不存在,跳过启动" return 1 fi # 启动 cron 服务 log_info "启动 cron 服务..." if /usr/sbin/cron start 2>/dev/null || /usr/sbin/cron 2>/dev/null; then log_success "cron 服务启动成功" sleep 2 if pgrep -x "cron" > /dev/null; then log_success "cron 服务运行正常" else log_warning "cron 服务可能未正常启动" fi else log_error "cron 服务启动失败" return 1 fi } # 安装组件 install_components() { log_info "开始安装组件..." artifact_dir=$(dirname "$VERSION_FILE_PATH") log_info "Artifact 目录: $artifact_dir" install_count=0 total_count=0 if [[ -f "$TEMP_DIR/install_order.txt" ]]; then total_count=$(wc -l < "$TEMP_DIR/install_order.txt") fi if [[ -f "$TEMP_DIR/install_order.txt" ]]; then while IFS= read -r filename; do install_count=$((install_count + 1)) # 从文件名中提取组件名(去掉时间戳后缀) component=$(echo "$filename" | sed 's/-[0-9]\{8\}-[0-9]\{6\}\.tar\.gz$//') log_info "[$install_count/$total_count] 安装 $component..." log_info " 文件名: $filename" # 直接使用完整的文件名 tar_file="$artifact_dir/$filename" if [[ ! -f "$tar_file" ]]; then log_error "找不到组件文件: $filename" log_info " 期望路径: $tar_file" log_info " 当前目录: $(pwd)" log_info " 目录内容:" ls -la "$artifact_dir" | while read line; do log_info " $line" done exit 1 fi log_info " 找到文件: $tar_file" # 解压到临时目录 component_temp_dir="$TEMP_DIR/$component" mkdir -p "$component_temp_dir" if tar -xzf "$tar_file" -C "$component_temp_dir" 2>/dev/null; then log_success " $component 解压完成" else log_error " $component 解压失败" exit 1 fi # 查找解压后的目录 extracted_dir="" for dir in "$component_temp_dir"/*; do if [[ -d "$dir" ]]; then extracted_dir="$dir" break fi done if [[ -z "$extracted_dir" ]]; then log_error " $component 解压后未找到目录" exit 1 fi # 执行安装脚本 if [[ -f "$extracted_dir/install.sh" ]]; then log_info " 执行 $component 安装脚本..." if (cd "$extracted_dir" && ./install.sh "$INSTALL_DIR"); then log_success " $component 安装完成" else log_error " $component 安装失败" exit 1 fi else log_error " $component 缺少 install.sh 文件" exit 1 fi # 将解压后的目录移动到安装目录,保留组件目录 component_install_dir="$INSTALL_DIR/$component" # 简化安装逻辑:直接删除旧目录,不进行备份 if [[ -d "$component_install_dir" ]]; then log_info " 组件目录已存在,删除旧版本: $component_install_dir" rm -rf "$component_install_dir" # log_info " 组件目录已存在,备份后更新: $component_install_dir" # mv "$component_install_dir" "${component_install_dir}.backup.$(date +%Y%m%d_%H%M%S)" fi mv "$extracted_dir" "$component_install_dir" log_success " 组件目录已保存: $component_install_dir" # 清理临时文件 rm -rf "$component_temp_dir" done < "$TEMP_DIR/install_order.txt" fi log_success "所有组件安装完成" } # 创建安装记录 create_install_record() { log_info "创建安装记录..." # 等待一段时间确保所有进程都已启动 log_info "等待进程启动..." sleep 3 local install_time=$(date -u +"%Y-%m-%dT%H:%M:%SZ") local install_record_file="$INSTALL_DIR/.install_record" # 创建 JSON 格式的安装记录 cat > "$install_record_file" << EOF { "version": "$VERSION", "build_time": "$BUILD_TIME", "install_time": "$install_time", "install_dir": "$INSTALL_DIR", "install_pid": $$, "components": { EOF # 添加组件信息 local first_component=true if [[ -f "$TEMP_DIR/components.txt" ]]; then while IFS= read -r line; do component=$(echo "$line" | cut -d':' -f1) version=$(echo "$line" | cut -d':' -f2) # 获取组件的进程信息 local component_pid="" # 根据组件名查找进程,使用多种方法确保能找到PID case "$component" in "node-exporter") # 尝试多种方式查找node_exporter进程 component_pid=$(pgrep -f "node_exporter" | head -1) if [[ -z "$component_pid" ]]; then component_pid=$(pgrep -f "node-exporter" | head -1) fi if [[ -z "$component_pid" ]]; then component_pid=$(ps aux | grep -v grep | grep "node_exporter" | awk '{print $2}' | head -1) fi ;; "dcgm-exporter") # 查找dcgm-exporter进程 component_pid=$(pgrep -f "dcgm-exporter" | head -1) if [[ -z "$component_pid" ]]; then component_pid=$(pgrep -f "dcgm_exporter" | head -1) fi if [[ -z "$component_pid" ]]; then component_pid=$(ps aux | grep -v grep | grep "dcgm-exporter" | awk '{print $2}' | head -1) fi ;; "fluent-bit") # 查找fluent-bit进程 component_pid=$(pgrep -f "fluent-bit" | head -1) if [[ -z "$component_pid" ]]; then component_pid=$(pgrep -f "fluent_bit" | head -1) fi if [[ -z "$component_pid" ]]; then component_pid=$(ps aux | grep -v grep | grep "fluent-bit" | awk '{print $2}' | head -1) fi ;; "argus-agent") # 查找argus-agent进程 component_pid=$(pgrep -f "argus-agent" | head -1) if [[ -z "$component_pid" ]]; then component_pid=$(ps aux | grep -v grep | grep "argus-agent" | awk '{print $2}' | head -1) fi ;; esac # 记录找到的PID信息 if [[ -n "$component_pid" ]]; then log_info " 找到 $component 进程 PID: $component_pid" else log_warning " 未找到 $component 进程" fi # 添加逗号分隔符 if [[ "$first_component" == "true" ]]; then first_component=false else echo "," >> "$install_record_file" fi # 添加组件信息 cat >> "$install_record_file" << EOF "$component": { "version": "$version", "pid": "$component_pid", "install_dir": "$INSTALL_DIR/$component" } EOF done < "$TEMP_DIR/components.txt" fi # 结束 JSON cat >> "$install_record_file" << EOF } } EOF log_success "安装记录已创建: $install_record_file" } # 检查cron任务是否已存在 check_cron_task_exists() { local task_pattern="$1" local temp_cron="$2" if grep -q "$task_pattern" "$temp_cron"; then return 0 # 任务已存在 else return 1 # 任务不存在 fi } # 设置健康检查定时任务 setup_health_check_cron() { log_info "设置健康检查定时任务..." # 直接使用当前安装目录,不依赖current软链接 # INSTALL_DIR 是 /opt/argus-metric/versions/1.34.0 local check_health_script="$INSTALL_DIR/check_health.sh" # 检查健康检查脚本是否存在 if [[ ! -f "$check_health_script" ]]; then log_error "健康检查脚本不存在: $check_health_script" return 1 fi # 确保脚本有执行权限 chmod +x "$check_health_script" # 创建临时crontab文件 local temp_cron="/tmp/crontab_$$" # 获取当前用户的crontab(如果存在) crontab -l 2>/dev/null > "$temp_cron" || touch "$temp_cron" # 检查并删除旧的健康检查任务 if check_cron_task_exists "check_health.sh" "$temp_cron"; then log_info "发现旧的健康检查定时任务,正在更新..." # 删除所有包含check_health.sh的行 grep -v "check_health.sh" "$temp_cron" > "$temp_cron.new" mv "$temp_cron.new" "$temp_cron" log_info "旧的健康检查定时任务已删除" fi # 添加新的定时任务(每5分钟执行一次) echo "# Argus-Metrics 健康检查定时任务" >> "$temp_cron" echo "*/5 * * * * $check_health_script >> $INSTALL_DIR/.health_cron.log 2>&1" >> "$temp_cron" # 安装新的crontab if crontab "$temp_cron"; then log_success "健康检查定时任务设置成功" log_info " 执行频率: 每5分钟" log_info " 日志文件: $INSTALL_DIR/.health_cron.log" log_info " 查看定时任务: crontab -l" log_info " 删除定时任务: crontab -e" else log_error "健康检查定时任务设置失败" rm -f "$temp_cron" return 1 fi # 清理临时文件 rm -f "$temp_cron" log_info "健康检查通过crontab自动执行" } # 设置 DNS 同步定时任务 setup_dns_sync_cron() { log_info "设置 DNS 同步定时任务..." # 使用当前版本目录中的 DNS 同步脚本 local sync_dns_script="$INSTALL_DIR/sync_dns.sh" # 检查 DNS 同步脚本是否存在 if [[ ! -f "$sync_dns_script" ]]; then log_warning "DNS 同步脚本不存在: $sync_dns_script" log_warning "跳过 DNS 同步定时任务设置" return 0 fi # 确保脚本有执行权限 chmod +x "$sync_dns_script" # 创建临时crontab文件 local temp_cron="/tmp/crontab_$$" # 获取当前用户的crontab(如果存在) crontab -l 2>/dev/null > "$temp_cron" || touch "$temp_cron" # 检查并删除旧的 DNS 同步任务 if check_cron_task_exists "sync_dns.sh" "$temp_cron"; then log_info "发现旧的 DNS 同步定时任务,正在更新..." # 删除所有包含sync_dns.sh的行 grep -v "sync_dns.sh" "$temp_cron" > "$temp_cron.new" mv "$temp_cron.new" "$temp_cron" log_info "旧的 DNS 同步定时任务已删除" fi # 添加新的定时任务(每1分钟执行一次) # 直接使用版本目录中的 DNS 同步脚本 echo "# Argus-Metrics DNS 同步定时任务" >> "$temp_cron" echo "* * * * * $sync_dns_script >> $INSTALL_DIR/.dns_sync.log 2>&1" >> "$temp_cron" # 安装新的crontab if crontab "$temp_cron"; then log_success "DNS 同步定时任务设置成功" log_info " 执行频率: 每1分钟" log_info " 日志文件: $INSTALL_DIR/.dns_sync.log" log_info " 查看定时任务: crontab -l" log_info " 删除定时任务: crontab -e" else log_error "DNS 同步定时任务设置失败" rm -f "$temp_cron" return 1 fi # 清理临时文件 rm -f "$temp_cron" log_info "DNS 同步通过crontab自动执行" } # 设置版本校验定时任务 setup_version_check_cron() { log_info "设置版本校验定时任务..." # 使用当前版本目录中的版本校验脚本 local check_version_script="$INSTALL_DIR/check_version.sh" # 检查脚本是否存在 if [[ ! -f "$check_version_script" ]]; then log_warning "版本校验脚本不存在: $check_version_script" log_info "跳过版本校验定时任务设置" return 0 fi # 确保脚本可执行 chmod +x "$check_version_script" # 创建临时crontab文件 local temp_cron="/tmp/crontab_$$" crontab -l > "$temp_cron" 2>/dev/null || touch "$temp_cron" # 检查是否已存在版本校验定时任务 if check_cron_task_exists "check_version.sh" "$temp_cron"; then log_info "发现旧的版本校验定时任务,正在更新..." # 删除所有包含check_version.sh的行 grep -v "check_version.sh" "$temp_cron" > "$temp_cron.new" mv "$temp_cron.new" "$temp_cron" log_info "旧的版本校验定时任务已删除" fi # 添加新的定时任务(每30分钟执行一次) echo "# Argus-Metrics 版本校验定时任务" >> "$temp_cron" echo "*/1 * * * * $check_version_script >> $INSTALL_DIR/.version_check.log 2>&1" >> "$temp_cron" # 安装新的crontab if crontab "$temp_cron"; then log_success "版本校验定时任务设置成功" log_info " 执行频率: 每1分钟" log_info " 日志文件: $INSTALL_DIR/.version_check.log" log_info " 查看定时任务: crontab -l" log_info " 删除定时任务: crontab -e" else log_error "版本校验定时任务设置失败" rm -f "$temp_cron" return 1 fi # 清理临时文件 rm -f "$temp_cron" log_info "版本校验通过crontab自动执行" } # 设置自动重启定时任务 setup_restart_cron() { log_info "设置自动重启定时任务..." # 使用当前版本目录中的重启脚本 local restart_script="$INSTALL_DIR/restart_unhealthy.sh" # 检查脚本是否存在 if [[ ! -f "$restart_script" ]]; then log_warning "重启脚本不存在: $restart_script" log_info "跳过自动重启定时任务设置" return 0 fi # 确保脚本可执行 chmod +x "$restart_script" # 创建临时crontab文件 local temp_cron="/tmp/crontab_$$" crontab -l > "$temp_cron" 2>/dev/null || touch "$temp_cron" # 检查是否已存在自动重启定时任务 if check_cron_task_exists "restart_unhealthy.sh" "$temp_cron"; then log_info "发现旧的自动重启定时任务,正在更新..." # 删除所有包含restart_unhealthy.sh的行 grep -v "restart_unhealthy.sh" "$temp_cron" > "$temp_cron.new" mv "$temp_cron.new" "$temp_cron" log_info "旧的自动重启定时任务已删除" fi # 添加新的定时任务(每2分钟执行一次) echo "# Argus-Metrics 自动重启定时任务" >> "$temp_cron" echo "*/2 * * * * $restart_script >> $INSTALL_DIR/.restart.log 2>&1" >> "$temp_cron" # 安装新的crontab if crontab "$temp_cron"; then log_success "自动重启定时任务设置成功" log_info " 执行频率: 每2分钟" log_info " 日志文件: $INSTALL_DIR/.restart.log" log_info " 查看定时任务: crontab -l" log_info " 删除定时任务: crontab -e" else log_error "自动重启定时任务设置失败" rm -f "$temp_cron" return 1 fi # 清理临时文件 rm -f "$temp_cron" log_info "自动重启检查通过crontab自动执行" } # 显示安装信息 show_install_info() { log_success "Argus-Metrics All-in-One 安装完成!" echo log_info "安装日志已保存到: $LOG_FILE" log_info "如需查看详细日志,请执行: cat $LOG_FILE" echo } cleanup() { if [[ -d "$TEMP_DIR" ]]; then rm -rf "$TEMP_DIR" fi } trap cleanup EXIT # 主函数 main() { echo "==========================================" echo " Argus-Metrics All-in-One 安装脚本 v1.0" echo "==========================================" echo # 初始化日志文件 mkdir -p "$INSTALL_DIR" echo "==========================================" > "$LOG_FILE" echo " Argus-Metrics All-in-One 安装日志" >> "$LOG_FILE" echo " 开始时间: $(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG_FILE" echo "==========================================" >> "$LOG_FILE" # 加载配置文件 load_config log_info "安装目录: $INSTALL_DIR" log_info "日志文件: $LOG_FILE" echo check_root check_system find_version_file create_install_dirs install_system_deps parse_version_info verify_checksums install_components copy_config_files create_install_record setup_health_check_cron setup_dns_sync_cron setup_version_check_cron setup_restart_cron # 注释掉立即执行健康检查,避免与cron任务重复执行 # log_info "立即执行一次健康检查..." # local check_health_script="$INSTALL_DIR/check_health.sh" # if [[ -f "$check_health_script" ]]; then # if "$check_health_script" >> "$INSTALL_DIR/.health_check.log" 2>&1; then # log_success "健康检查执行完成" # else # log_warning "健康检查执行失败,请检查日志: $INSTALL_DIR/.health_check.log" # fi # else # log_warning "健康检查脚本不存在: $check_health_script" # fi show_install_info } if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then main "$@" fi