Files
palladium-monitor/install_z1_agent.sh
T
Your Name 8945073ec6 del
2026-07-08 11:25:50 +08:00

218 lines
8.6 KiB
Bash
Executable File

#!/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 <<EOF
Palladium Z1 监控客户端安装脚本
用法:
$0 --url URL [--host NAME] [--env ENV_SCRIPT] [--interval MINUTES] [--uninstall]
必选 (首次安装):
--url URL 监控服务器 API 地址 (例如 http://10.0.0.10:5100/api/collect)
可选:
--host NAME 本机标签 (默认: hostname)
--env ENV_SCRIPT VXE env.csh / env.sh 绝对路径
--interval MINUTES 采集间隔分钟数 (默认: 30)
--timeout SECONDS test_server 超时 (默认: 300)
--retries N 推送失败重试次数 (默认: 3)
--uninstall 卸载 (保留日志和安装目录, 仅移除 crontab 和脚本)
示例:
$0 --url http://10.0.0.10:5100/api/collect --host scmp03 \\
--env /edatools/vxe/VXE23.03.001/bin/env.csh --interval 30
EOF
}
UNINSTALL=0
URL=""
HOST="$(hostname -s 2>/dev/null || hostname)"
ENV_SCRIPT=""
INTERVAL=30
TIMEOUT=$DEFAULT_TIMEOUT
RETRIES=$DEFAULT_RETRIES
while [[ $# -gt 0 ]]; do
case "$1" in
--url) URL="$2"; shift 2 ;;
--host) HOST="$2"; shift 2 ;;
--env) ENV_SCRIPT="$2"; shift 2 ;;
--interval) INTERVAL="$2"; shift 2 ;;
--timeout) TIMEOUT="$2"; shift 2 ;;
--retries) RETRIES="$2"; shift 2 ;;
--uninstall) UNINSTALL=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "未知参数: $1" >&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 <<EOF
════════════════════════════════════════════════════════════════════════════
✅ 安装完成
脚本: $INSTALL_DIR/collect.py
日志: $LOG_FILE (主日志)
${LOG_FILE}.cron (cron 自己的输出)
Crontab: 每 $INTERVAL 分钟一次
监控服务器: $URL
主机标签: $HOST
卸载: sudo $0 --uninstall
════════════════════════════════════════════════════════════════════════════
EOF