From 515a0a82fdf27fb580a8577a0eec42d55b8ecc9b Mon Sep 17 00:00:00 2001 From: xzx3344521 Date: Fri, 31 Oct 2025 19:28:57 +0800 Subject: [PATCH] Create BorgBackup --- BorgBackup | 476 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 BorgBackup diff --git a/BorgBackup b/BorgBackup new file mode 100644 index 0000000..0f1503e --- /dev/null +++ b/BorgBackup @@ -0,0 +1,476 @@ +#!/bin/bash + +# BorgBackup 智能安装配置脚本 +set -e + +# 颜色定义 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +# 日志函数 +log() { + echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +warn() { + echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" +} + +error() { + echo -e "${RED}[ERROR]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" + exit 1 +} + +# 检查系统 +check_system() { + log "检查系统环境..." + + # 检查操作系统 + if [ ! -f /etc/os-release ]; then + error "无法检测操作系统" + fi + + source /etc/os-release + log "检测到系统: $NAME $VERSION" + + # 检查架构 + ARCH=$(uname -m) + log "系统架构: $ARCH" + + # 检查磁盘空间 + DISK_SPACE=$(df /tmp | awk 'NR==2 {print $4}') + if [ "$DISK_SPACE" -lt 1048576 ]; then # 小于 1GB + warn "磁盘空间可能不足 (当前: ${DISK_SPACE}KB)" + read -p "是否继续? (y/N): " -n 1 -r + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + error "安装中止" + fi + fi + + # 检查内存 + MEMORY=$(free -m | awk 'NR==2{print $2}') + if [ "$MEMORY" -lt 512 ]; then + warn "内存较小 (当前: ${MEMORY}MB),可能会影响备份性能" + fi +} + +# 安装依赖 +install_dependencies() { + log "安装系统依赖..." + + # 根据系统类型安装依赖 + if command -v apt >/dev/null 2>&1; then + # Debian/Ubuntu + sudo apt update || warn "apt update 失败,尝试继续..." + sudo apt install -y \ + python3 \ + python3-pip \ + curl \ + wget \ + fuse \ + pv \ + cron \ + || error "依赖安装失败" + + elif command -v yum >/dev/null 2>&1; then + # CentOS/RHEL + sudo yum install -y \ + python3 \ + python3-pip \ + curl \ + wget \ + fuse \ + pv \ + cronie \ + || error "依赖安装失败" + + elif command -v dnf >/dev/null 2>&1; then + # Fedora + sudo dnf install -y \ + python3 \ + python3-pip \ + curl \ + wget \ + fuse \ + pv \ + cronie \ + || error "依赖安装失败" + + else + error "不支持的包管理器" + fi +} + +# 安装 BorgBackup +install_borg() { + log "安装 BorgBackup..." + + # 检查是否已安装 + if command -v borg >/dev/null 2>&1; then + CURRENT_VERSION=$(borg --version) + log "BorgBackup 已安装: $CURRENT_VERSION" + read -p "是否重新安装? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + return 0 + fi + fi + + # 多种安装方式 + log "尝试通过系统包管理器安装..." + if command -v apt >/dev/null 2>&1; then + sudo apt install -y borgbackup && return 0 + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y borgbackup && return 0 + elif command -v dnf >/dev/null 2>&1; then + sudo dnf install -y borgbackup && return 0 + fi + + # 包管理器安装失败,使用 pip + warn "包管理器安装失败,尝试使用 pip 安装..." + sudo pip3 install borgbackup || { + # 如果 pip 安装失败,尝试使用 conda + if command -v conda >/dev/null 2>&1; then + warn "尝试使用 conda 安装..." + conda install -c conda-forge borgbackup || error "BorgBackup 安装失败" + else + error "所有安装方式都失败,请手动安装" + fi + } + + log "BorgBackup 安装成功: $(borg --version)" +} + +# 安装 rclone +install_rclone() { + log "安装 rclone..." + + if command -v rclone >/dev/null 2>&1; then + log "rclone 已安装: $(rclone version | head -n1)" + return 0 + fi + + # 使用官方安装脚本 + curl https://rclone.org/install.sh | sudo bash || { + # 如果脚本安装失败,尝试包管理器 + warn "脚本安装失败,尝试包管理器..." + if command -v apt >/dev/null 2>&1; then + sudo apt install -y rclone + elif command -v yum >/dev/null 2>&1; then + sudo yum install -y rclone + else + error "rclone 安装失败" + fi + } + + log "rclone 安装成功" +} + +# 交互式配置 rclone +configure_rclone() { + log "配置云存储..." + + echo + echo "=== 云存储服务商选择 ===" + echo "1) Cloudflare R2 (推荐)" + echo "2) AWS S3" + echo "3) Backblaze B2" + echo "4) Google Cloud Storage" + echo "5) 阿里云 OSS" + echo "6) 腾讯云 COS" + echo "7) 其他 S3 兼容服务" + echo "8) 跳过(仅本地备份)" + + read -p "请选择服务商 [1-8]: " provider_choice + + case $provider_choice in + 1) + remote_name="r2" + provider="Cloudflare R2" + endpoint_prompt="R2 端点 (通常为: https://.r2.cloudflarestorage.com)" + region="auto" + ;; + 2) + remote_name="s3" + provider="Amazon S3" + endpoint_prompt="S3 端点 (留空使用默认): " + region_prompt="区域 (例如: us-east-1): " + ;; + 3) + remote_name="b2" + provider="Backblaze B2" + endpoint_prompt="B2 端点 (留空使用默认): " + region="" + ;; + 4) + remote_name="gcs" + provider="Google Cloud Storage" + endpoint_prompt="GCS 端点 (留空使用默认): " + region="" + ;; + 5) + remote_name="oss" + provider="Aliyun OSS" + endpoint_prompt="OSS 端点 (例如: https://oss-cn-hangzhou.aliyuncs.com): " + region="" + ;; + 6) + remote_name="cos" + provider="Tencent COS" + endpoint_prompt="COS 端点 (例如: https://cos.ap-beijing.myqcloud.com): " + region="" + ;; + 7) + remote_name="s3-custom" + provider="自定义 S3 兼容" + endpoint_prompt="S3 兼容端点: " + region_prompt="区域: " + ;; + 8) + log "跳过远程存储配置" + return 0 + ;; + *) + error "无效选择" + ;; + esac + + # 获取配置信息 + echo + echo "=== 配置 $provider ===" + read -p "请输入远程存储名称 [默认: $remote_name]: " input_remote + remote_name=${input_remote:-$remote_name} + + read -p "$endpoint_prompt" endpoint + if [ -n "$endpoint" ]; then + endpoint_option="$endpoint" + fi + + if [ -n "$region_prompt" ]; then + read -p "$region_prompt" region + fi + + echo + echo "=== API 密钥信息 ===" + echo "在哪里找到密钥:" + case $provider_choice in + 1) echo "- Cloudflare Dashboard → R2 → API Tokens" ;; + 2) echo "- AWS Console → IAM → Users → Security credentials" ;; + 3) echo "- Backblaze → My Account → App Keys" ;; + 4) echo "- Google Cloud Console → Storage → Settings → Interoperability" ;; + 5) echo "- 阿里云控制台 → 访问控制 → 用户管理" ;; + 6) echo "- 腾讯云控制台 → 访问管理 → API密钥管理" ;; + 7) echo "- 查看您的 S3 兼容服务商文档" ;; + esac + echo + + read -p "Access Key ID: " access_key + read -s -p "Secret Access Key: " secret_key + echo + + # 配置 rclone + log "配置 rclone 远程存储: $remote_name" + + rclone config create \ + "$remote_name" \ + s3 \ + provider "Other" \ + env_auth false \ + access_key_id "$access_key" \ + secret_access_key "$secret_key" \ + ${endpoint:+"endpoint" "$endpoint"} \ + ${region:+"region" "$region"} \ + acl private \ + || error "rclone 配置失败" + + # 测试连接 + log "测试连接..." + if rclone lsd "$remote_name:" >/dev/null 2>&1; then + log "连接测试成功!" + else + warn "连接测试失败,但配置已保存。请检查网络和密钥。" + fi + + REMOTE_CONFIGURED=1 + CONFIGURED_REMOTE="$remote_name" +} + +# 创建备份脚本 +create_backup_scripts() { + log "创建备份脚本..." + + local scripts_dir="$HOME/backup-scripts" + mkdir -p "$scripts_dir" + + # 主备份脚本 + cat > "$scripts_dir/backup-system.sh" << 'EOF' +#!/bin/bash +# BorgBackup 系统备份脚本 + +set -e + +# 配置 +BACKUP_NAME="$(hostname)-system" +LOCAL_REPO="$HOME/borg-repo" +LOG_FILE="$HOME/backup-scripts/backup.log" +CONFIG_FILE="$HOME/backup-scripts/backup.conf" + +# 加载配置 +if [ -f "$CONFIG_FILE" ]; then + source "$CONFIG_FILE" +fi + +# 颜色 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +NC='\033[0m' + +log() { echo -e "${GREEN}[INFO]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $(date '+%Y-%m-%d %H:%M:%S') - $1" | tee -a "$LOG_FILE"; } + +# 初始化仓库 +init_repo() { + if [ ! -d "$LOCAL_REPO" ]; then + log "初始化 Borg 仓库..." + borg init --encryption=repokey-blake2 "$LOCAL_REPO" 2>/dev/null || true + fi +} + +# 执行备份 +create_backup() { + local archive_name="$BACKUP_NAME-$(date +%Y%m%d-%H%M%S)" + + log "创建备份: $archive_name" + + sudo borg create \ + --compression lz4 \ + --stats \ + --progress \ + --exclude-caches \ + --exclude '/var/cache/*' \ + --exclude '/var/tmp/*' \ + --exclude '/tmp/*' \ + --exclude '/proc/*' \ + --exclude '/sys/*' \ + --exclude '/dev/*' \ + --exclude '/mnt/*' \ + --exclude '/media/*' \ + --exclude '/run/*' \ + --exclude '/boot/*' \ + --exclude '/lost+found' \ + --exclude '*.pyc' \ + --exclude '*.swap' \ + --exclude '*.tmp' \ + "$LOCAL_REPO::$archive_name" \ + / 2>&1 | tee -a "$LOG_FILE" +} + +# 清理旧备份 +prune_backups() { + log "清理旧备份..." + + borg prune --list --stats \ + --keep-daily=7 \ + --keep-weekly=4 \ + --keep-monthly=3 \ + "$LOCAL_REPO" 2>&1 | tee -a "$LOG_FILE" +} + +# 同步到远程 +sync_to_remote() { + if [ -n "$REMOTE_CONFIG" ]; then + log "同步到远程存储: $REMOTE_CONFIG" + rclone sync "$LOCAL_REPO" "$REMOTE_CONFIG" --progress 2>&1 | tee -a "$LOG_FILE" + fi +} + +# 主函数 +main() { + log "=== 开始备份任务 ===" + + init_repo + create_backup + prune_backups + sync_to_remote + + log "=== 备份任务完成 ===" +} + +main "$@" +EOF + + # 如果配置了远程存储,更新配置文件 + if [ "$REMOTE_CONFIGURED" = "1" ]; then + echo "REMOTE_CONFIG=\"$CONFIGURED_REMOTE:backups/$(hostname)\"" > "$scripts_dir/backup.conf" + fi + + chmod +x "$scripts_dir/backup-system.sh" + log "备份脚本创建完成: $scripts_dir/backup-system.sh" +} + +# 显示总结信息 +show_summary() { + echo + echo "=== 安装完成 ===" + echo -e "${GREEN}✓ BorgBackup 已安装${NC}" + echo -e "${GREEN}✓ rclone 已安装${NC}" + + if [ "$REMOTE_CONFIGURED" = "1" ]; then + echo -e "${GREEN}✓ 远程存储已配置: $CONFIGURED_REMOTE${NC}" + else + echo -e "${YELLOW}⚠ 未配置远程存储(仅本地备份)${NC}" + fi + + echo + echo "=== 下一步操作 ===" + echo "1. 首次备份: ~/backup-scripts/backup-system.sh" + echo "2. 设置定时任务: crontab -e" + echo "3. 查看备份: borg list ~/borg-repo" + + if [ "$REMOTE_CONFIGURED" = "1" ]; then + echo "4. 查看远程备份: rclone lsd $CONFIGURED_REMOTE:" + fi + + echo + echo "=== 重要提醒 ===" + echo "• 备份 Borg 密钥: ~/borg-repo/keyfile" + echo "• 定期测试恢复功能" + echo "• 监控备份日志: ~/backup-scripts/backup.log" +} + +# 主函数 +main() { + clear + echo -e "${BLUE}" + echo "╔══════════════════════════════════════╗" + echo "║ BorgBackup 智能安装脚本 ║" + echo "║ 适用于多平台系统备份 ║" + echo "╚══════════════════════════════════════╝" + echo -e "${NC}" + + # 检查 root 权限 + if [ "$EUID" -eq 0 ]; then + warn "不建议使用 root 用户运行此脚本" + read -p "是否继续? (y/N): " -n 1 -r + echo + if [[ ! $REPLY =~ ^[Yy]$ ]]; then + error "请使用普通用户运行" + fi + fi + + # 执行安装步骤 + check_system + install_dependencies + install_borg + install_rclone + configure_rclone + create_backup_scripts + show_summary +} + +# 运行主函数 +main "$@"