#!/bin/bash ############################################################################### # Docker Backup 远程安装脚本 # 功能:安装依赖、下载文件、配置 systemd 服务 # 使用:bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) ############################################################################### set -e set -o pipefail # 颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Gitea 仓库地址 REPO_URL="https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main" # 安装路径 BIN_DIR="/usr/local/bin" CONFIG_DIR="/etc/docker-backup" SYSTEMD_DIR="/etc/systemd/system" # 默认服务名称 DEFAULT_SERVICE_NAME="docker-backup" SERVICE_NAME="${SERVICE_NAME:-$DEFAULT_SERVICE_NAME}" # 默认定时计划 DEFAULT_SCHEDULE="*-*-* 02:00:00" # 每天凌晨 2 点 SCHEDULE="${SCHEDULE:-$DEFAULT_SCHEDULE}" ############################################################################### # 日志函数 ############################################################################### log_info() { echo -e "${GREEN}[INFO]${NC} $@" } log_warn() { echo -e "${YELLOW}[WARN]${NC} $@" } log_error() { echo -e "${RED}[ERROR]${NC} $@" } log_step() { echo -e "\n${BLUE}==>${NC} $@" } ############################################################################### # 检查是否以 root 权限运行 ############################################################################### check_root() { if [[ $EUID -ne 0 ]]; then log_error "此脚本需要 root 权限运行" log_info "请使用: sudo bash <(curl -sL ...)" exit 1 fi } ############################################################################### # 检测操作系统 ############################################################################### detect_os() { if [[ -f /etc/os-release ]]; then . /etc/os-release OS=$ID OS_VERSION=$VERSION_ID else log_error "无法检测操作系统类型" exit 1 fi log_info "检测到操作系统: $OS $OS_VERSION" } ############################################################################### # 安装 yq ############################################################################### install_yq() { log_step "检查 yq 是否已安装..." if command -v yq &> /dev/null; then log_info "yq 已安装: $(yq --version)" return 0 fi log_info "yq 未安装,正在安装..." # 检测系统架构 local arch=$(uname -m) case $arch in x86_64) arch="amd64" ;; aarch64|arm64) arch="arm64" ;; armv7l) arch="arm" ;; *) log_error "不支持的系统架构: $arch" exit 1 ;; esac # 下载并安装 yq local yq_version="v4.40.5" local yq_url="https://github.com/mikefarah/yq/releases/download/${yq_version}/yq_linux_${arch}" log_info "下载 yq ${yq_version} for ${arch}..." if command -v wget &> /dev/null; then wget -q "${yq_url}" -O /usr/local/bin/yq elif command -v curl &> /dev/null; then curl -sL "${yq_url}" -o /usr/local/bin/yq else log_error "需要 wget 或 curl 来下载 yq" exit 1 fi chmod +x /usr/local/bin/yq if command -v yq &> /dev/null; then log_info "yq 安装成功: $(yq --version)" else log_error "yq 安装失败" exit 1 fi } ############################################################################### # 安装其他依赖 ############################################################################### install_dependencies() { log_step "检查并安装依赖工具..." local deps=("tar" "gzip" "docker" "find") local missing_deps=() for dep in "${deps[@]}"; do if ! command -v "$dep" &> /dev/null; then missing_deps+=("$dep") fi done if [[ ${#missing_deps[@]} -eq 0 ]]; then log_info "所有依赖工具已安装" return 0 fi log_warn "缺少以下工具: ${missing_deps[*]}" case $OS in ubuntu|debian) log_info "使用 apt 安装依赖..." apt-get update -qq apt-get install -y -qq "${missing_deps[@]}" docker.io ;; centos|rhel|fedora) log_info "使用 yum/dnf 安装依赖..." if command -v dnf &> /dev/null; then dnf install -y -q "${missing_deps[@]}" docker else yum install -y -q "${missing_deps[@]}" docker fi ;; *) log_error "不支持的操作系统,请手动安装: ${missing_deps[*]}" exit 1 ;; esac log_info "依赖安装完成" } ############################################################################### # 下载并部署文件 ############################################################################### deploy_files() { log_step "从远程仓库下载文件..." # 创建必要的目录 mkdir -p "${BIN_DIR}" mkdir -p "${CONFIG_DIR}" mkdir -p "${SYSTEMD_DIR}" # 下载备份脚本 log_info "下载 backup.sh..." if command -v wget &> /dev/null; then wget -q "${REPO_URL}/bin/backup.sh" -O "${BIN_DIR}/docker-backup" else curl -sL "${REPO_URL}/bin/backup.sh" -o "${BIN_DIR}/docker-backup" fi chmod +x "${BIN_DIR}/docker-backup" # 下载清理脚本 log_info "下载 cleanup.sh..." if command -v wget &> /dev/null; then wget -q "${REPO_URL}/bin/cleanup.sh" -O "${BIN_DIR}/docker-backup-cleanup" else curl -sL "${REPO_URL}/bin/cleanup.sh" -o "${BIN_DIR}/docker-backup-cleanup" fi chmod +x "${BIN_DIR}/docker-backup-cleanup" # 下载配置文件示例 if [[ ! -f "${CONFIG_DIR}/config.yml" ]]; then log_info "下载配置文件示例..." if command -v wget &> /dev/null; then wget -q "${REPO_URL}/config/backup.yml.example" -O "${CONFIG_DIR}/config.yml" else curl -sL "${REPO_URL}/config/backup.yml.example" -o "${CONFIG_DIR}/config.yml" fi log_warn "请编辑配置文件: ${CONFIG_DIR}/config.yml" else log_info "配置文件已存在,跳过" fi log_info "文件部署完成" } ############################################################################### # 配置 systemd 服务 ############################################################################### setup_systemd() { log_step "配置 systemd 服务..." # 生成 service 文件 log_info "生成 ${SERVICE_NAME}.service..." cat > "${SYSTEMD_DIR}/${SERVICE_NAME}.service" << EOF [Unit] Description=Docker Backup Service Documentation=https://gitea.bcde.io/wangdefa/docker-backup After=network.target docker.service Requires=docker.service [Service] Type=oneshot User=root Group=root # 执行备份脚本 ExecStart=${BIN_DIR}/docker-backup # 标准输出和错误输出 StandardOutput=journal StandardError=journal # 超时设置(30分钟) TimeoutStartSec=1800 # 资源限制 Nice=19 IOSchedulingClass=idle [Install] WantedBy=multi-user.target EOF # 生成 timer 文件 log_info "生成 ${SERVICE_NAME}.timer..." cat > "${SYSTEMD_DIR}/${SERVICE_NAME}.timer" << EOF [Unit] Description=Docker Backup Timer Documentation=https://gitea.bcde.io/wangdefa/docker-backup Requires=${SERVICE_NAME}.service [Timer] # 定时执行时间 OnCalendar=${SCHEDULE} # 如果错过了执行时间,启动时立即执行一次 Persistent=true # 随机延迟(0-10分钟),避免多个任务同时执行 RandomizedDelaySec=10min [Install] WantedBy=timers.target EOF # 重新加载 systemd log_info "重新加载 systemd..." systemctl daemon-reload log_info "systemd 服务配置完成" } ############################################################################### # 启用并启动服务 ############################################################################### enable_service() { log_step "启用 systemd 服务..." # 启用 timer log_info "启用 ${SERVICE_NAME}.timer..." systemctl enable "${SERVICE_NAME}.timer" # 启动 timer log_info "启动 ${SERVICE_NAME}.timer..." systemctl start "${SERVICE_NAME}.timer" # 检查状态 log_info "服务状态:" systemctl status "${SERVICE_NAME}.timer" --no-pager || true log_info "定时任务已启用" } ############################################################################### # 测试备份 ############################################################################### test_backup() { log_step "测试备份功能..." read -p "是否立即执行一次备份测试? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then log_info "执行备份测试..." "${BIN_DIR}/docker-backup" || log_error "备份测试失败,请检查配置和日志" else log_info "跳过备份测试" fi } ############################################################################### # 显示安装信息 ############################################################################### show_info() { echo "" echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ Docker Backup 安装完成! ║${NC}" echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" echo -e "${BLUE}安装信息:${NC}" echo " - 备份脚本: ${BIN_DIR}/docker-backup" echo " - 清理脚本: ${BIN_DIR}/docker-backup-cleanup" echo " - 配置文件: ${CONFIG_DIR}/config.yml" echo " - 服务名称: ${SERVICE_NAME}" echo "" echo -e "${BLUE}常用命令:${NC}" echo " # 查看定时任务状态" echo " systemctl status ${SERVICE_NAME}.timer" echo "" echo " # 查看定时计划" echo " systemctl list-timers ${SERVICE_NAME}.timer" echo "" echo " # 手动执行备份" echo " docker-backup" echo "" echo " # 列出所有备份" echo " docker-backup-cleanup --list" echo "" echo " # 清理旧备份" echo " docker-backup-cleanup --auto" echo "" echo " # 停止定时任务" echo " systemctl stop ${SERVICE_NAME}.timer" echo "" echo " # 禁用定时任务" echo " systemctl disable ${SERVICE_NAME}.timer" echo "" echo -e "${YELLOW}重要提示:${NC}" echo " 1. 请编辑配置文件以适应您的环境:" echo " vi ${CONFIG_DIR}/config.yml" echo "" echo " 2. 修改配置后无需重启服务,下次执行时自动生效" echo "" echo " 3. 查看下次执行时间:" echo " systemctl list-timers | grep ${SERVICE_NAME}" echo "" echo " 4. 查看备份日志:" echo " journalctl -u ${SERVICE_NAME}.service -f" echo "" } ############################################################################### # 卸载函数 ############################################################################### uninstall() { log_step "卸载 Docker Backup..." # 停止并禁用服务 if systemctl is-active --quiet "${SERVICE_NAME}.timer"; then log_info "停止 ${SERVICE_NAME}.timer..." systemctl stop "${SERVICE_NAME}.timer" fi if systemctl is-enabled --quiet "${SERVICE_NAME}.timer"; then log_info "禁用 ${SERVICE_NAME}.timer..." systemctl disable "${SERVICE_NAME}.timer" fi # 删除 systemd 文件 log_info "删除 systemd 文件..." rm -f "${SYSTEMD_DIR}/${SERVICE_NAME}.service" rm -f "${SYSTEMD_DIR}/${SERVICE_NAME}.timer" # 重新加载 systemd systemctl daemon-reload # 删除脚本文件 log_info "删除脚本文件..." rm -f "${BIN_DIR}/docker-backup" rm -f "${BIN_DIR}/docker-backup-cleanup" # 删除配置文件 read -p "是否删除配置目录 ${CONFIG_DIR}? (y/n) " -n 1 -r echo if [[ $REPLY =~ ^[Yy]$ ]]; then log_info "删除配置目录..." rm -rf "${CONFIG_DIR}" else log_info "保留配置目录" fi log_info "卸载完成" exit 0 } ############################################################################### # 显示使用帮助 ############################################################################### show_usage() { cat << EOF Docker Backup 远程安装脚本 用法: bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) [选项] 选项: -h, --help 显示此帮助信息 -n, --name NAME 指定服务名称 (默认: ${DEFAULT_SERVICE_NAME}) -s, --schedule SCHEDULE 指定定时计划 (默认: ${DEFAULT_SCHEDULE}) -u, --uninstall 卸载 Docker Backup 定时计划示例: "daily" 每天执行 "*-*-* 02:00:00" 每天凌晨 2 点 "Mon *-*-* 02:00:00" 每周一凌晨 2 点 "*-*-01 02:00:00" 每月 1 号凌晨 2 点 "hourly" 每小时执行 示例: # 默认安装 bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) # 自定义服务名称 bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) --name mybackup # 自定义定时计划(每天早上 6 点) bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) --schedule "*-*-* 06:00:00" # 卸载 bash <(curl -sL https://gitea.bcde.io/wangdefa/docker-backup/raw/branch/main/install.sh) --uninstall EOF } ############################################################################### # 主函数 ############################################################################### main() { # 解析参数 while [[ $# -gt 0 ]]; do case $1 in -h|--help) show_usage exit 0 ;; -n|--name) SERVICE_NAME="$2" shift 2 ;; -s|--schedule) SCHEDULE="$2" shift 2 ;; -u|--uninstall) check_root uninstall ;; *) log_error "未知选项: $1" show_usage exit 1 ;; esac done # 显示欢迎信息 echo -e "${GREEN}╔═══════════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║ 欢迎使用 Docker Backup 安装程序 ║${NC}" echo -e "${GREEN}╚═══════════════════════════════════════════════════════════════╝${NC}" echo "" echo "安装配置:" echo " - 服务名称: ${SERVICE_NAME}" echo " - 定时计划: ${SCHEDULE}" echo " - 配置目录: ${CONFIG_DIR}" echo " - 脚本目录: ${BIN_DIR}" echo "" # 检查 root 权限 check_root # 检测操作系统 detect_os # 安装 yq install_yq # 安装其他依赖 install_dependencies # 部署文件 deploy_files # 配置 systemd setup_systemd # 启用服务 enable_service # 测试备份 test_backup # 显示安装信息 show_info } # 执行主函数 main "$@"