#!/bin/bash #═══════════════════════════════════════════════════════════════════════════════ # install_z1_agent.sh — Palladium Z1 主机端 collect.py 一键部署脚本 #═══════════════════════════════════════════════════════════════════════════════ # 用法: # sudo ./install_z1_agent.sh --url http://MONITOR_HOST:5100/api/collect --host scmp03 # sudo ./install_z1_agent.sh --uninstall # # 关键点: # - 默认 30 分钟一次 (cron */30) # - 自动检测 env.csh / env.sh (如不存在则提示用户提供 --env) # - 幂等: 重复运行会先卸载旧的 # - 保险模式: 不会覆盖用户已有 crontab, 也不会 rm 任何文件 #═══════════════════════════════════════════════════════════════════════════════ set -euo pipefail # ─── Defaults ──────────────────────────────────────────────────────────────── INSTALL_DIR="/opt/palladium-monitor" LOG_DIR="/var/log" LOG_FILE="$LOG_DIR/palladium-collect.log" CRON_TAG="palladium-monitor-collect" # crontab 注释标记, 便于后续识别 DEFAULT_TIMEOUT=300 DEFAULT_RETRIES=3 DEFAULT_RETRY_DELAY=5 # ─── CLI ───────────────────────────────────────────────────────────────────── usage() { cat <&2; usage; exit 1 ;; esac done # ─── Helpers ────────────────────────────────────────────────────────────────── log_info() { echo "[INFO] $*"; } log_warn() { echo "[WARN] $*" >&2; } log_error() { echo "[ERROR] $*" >&2; } require_root() { if [[ $EUID -ne 0 ]]; then log_error "请用 root 运行: sudo $0 $*" exit 1 fi } # 备份当前 crontab backup_crontab() { local bak="/tmp/crontab.backup.$(date +%Y%m%d_%H%M%S)" if crontab -l >/dev/null 2>&1; then crontab -l > "$bak" log_info "已备份现有 crontab → $bak" else : > "$bak" log_info "当前用户无 crontab, 备份为空文件 $bak" fi } # 移除已存在的同标记行 (幂等) remove_existing_cron() { if crontab -l 2>/dev/null | grep -q "$CRON_TAG"; then log_info "检测到旧任务, 先移除 (幂等)" crontab -l | grep -v "$CRON_TAG" | grep -v "^#" | crontab - fi } # ─── Uninstall ──────────────────────────────────────────────────────────────── do_uninstall() { require_root log_info "卸载: 移除 crontab 任务 (标签: $CRON_TAG)" remove_existing_cron if [[ -f "$INSTALL_DIR/collect.py" ]]; then log_info "移除脚本: $INSTALL_DIR/collect.py" rm -f "$INSTALL_DIR/collect.py" fi log_info "卸载完成. 日志保留在 $LOG_FILE (如不再需要请手动清理)" exit 0 } [[ "$UNINSTALL" -eq 1 ]] && do_uninstall # ─── Install ────────────────────────────────────────────────────────────────── require_root if [[ -z "$URL" ]]; then log_error "--url 是必选参数" usage exit 1 fi # 校验 URL 格式 (基本) if ! [[ "$URL" =~ ^https?://[^:]+:[0-9]+/.* ]]; then log_warn "URL 格式异常: $URL (期望 http://host:port/path)" read -r -p "仍要继续? [y/N] " ans [[ "$ans" =~ ^[Yy]$ ]] || { log_info "已取消"; exit 1; } fi # 校验 env 脚本 (如果指定) if [[ -n "$ENV_SCRIPT" ]]; then if [[ ! -f "$ENV_SCRIPT" ]]; then log_error "env 脚本不存在: $ENV_SCRIPT" exit 1 fi log_info "env 脚本校验通过: $ENV_SCRIPT" fi # 创建安装目录 log_info "创建安装目录: $INSTALL_DIR" mkdir -p "$INSTALL_DIR" # 复制 collect.py SCRIPT_SRC="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/collect.py" if [[ ! -f "$SCRIPT_SRC" ]]; then log_error "未找到 collect.py, 请把脚本和本安装器放在同一目录" exit 1 fi install -m 0755 "$SCRIPT_SRC" "$INSTALL_DIR/collect.py" log_info "已安装: $INSTALL_DIR/collect.py" # 确保 requests 可用 if ! python3 -c "import requests" 2>/dev/null; then log_warn "python3 'requests' 未安装, 尝试安装..." if command -v pip3 >/dev/null; then pip3 install requests elif command -v pip >/dev/null; then pip install requests else log_error "找不到 pip/pip3, 请手动安装 requests 后重试" exit 1 fi fi log_info "Python 'requests' 模块可用" # 准备日志 touch "$LOG_FILE" 2>/dev/null || { log_error "无法写入 $LOG_FILE"; exit 1; } chmod 0644 "$LOG_FILE" # 安装 crontab log_info "安装 crontab — 每 $INTERVAL 分钟, 标签: $CRON_TAG" backup_crontab remove_existing_cron # 构造 cron 行 CRON_LINE="*/${INTERVAL} * * * * /usr/bin/python3 ${INSTALL_DIR}/collect.py --url ${URL} --host ${HOST}" if [[ -n "$ENV_SCRIPT" ]]; then CRON_LINE="${CRON_LINE} --env ${ENV_SCRIPT}" fi CRON_LINE="${CRON_LINE} --timeout ${TIMEOUT} --retries ${RETRIES} --log ${LOG_FILE} >> ${LOG_FILE}.cron 2>&1 # ${CRON_TAG}" # 写入新 crontab (保留旧任务) { crontab -l 2>/dev/null; echo "$CRON_LINE"; } | crontab - log_info "crontab 已更新" # ─── 验证安装 ──────────────────────────────────────────────────────────────── log_info "── 当前 crontab 中本任务相关行 ──" crontab -l | grep "$CRON_TAG" || log_warn "未找到新行, 请检查" log_info "── 立即跑一次 dry-run 验证脚本可执行 ──" "$INSTALL_DIR/collect.py" \ --url "$URL" --host "$HOST" \ ${ENV_SCRIPT:+--env "$ENV_SCRIPT"} \ --timeout 30 --retries 1 --retry-delay 1 \ --dry-run 2>&1 | tail -20 || log_warn "dry-run 失败 (test_server 可能在 VXE 工具链环境外, 这是正常的)" cat <