实战:用 Shell 脚本自动备份网站和数据库,并上传到云存储

1. 备份方案概述

在本教程中,我们将创建一个完整的自动化备份系统,用于备份网站文件和数据库,并将备份文件上传到云存储。该系统包含错误处理、日志记录和通知功能,适合生产环境使用。

graph TD A[开始备份任务] --> B[初始化环境和变量] B --> C[备份网站文件] C --> D[备份MySQL数据库] D --> E[备份PostgreSQL数据库] E --> F[压缩备份文件] F --> G{上传到云存储} G --> H[AWS S3] G --> I[Google Cloud Storage] G --> J[阿里云OSS] H --> K[清理旧备份] I --> K J --> K K --> L[发送通知] L --> M[备份完成] style A fill:#2C3E50,stroke:#2C3E50,color:#fff style M fill:#27AE60,stroke:#27AE60,color:#fff style G fill:#E74C3C,stroke:#E74C3C,color:#fff style C fill:#3498DB,stroke:#3498DB,color:#fff style D fill:#3498DB,stroke:#3498DB,color:#fff style E fill:#3498DB,stroke:#3498DB,color:#fff

2. 环境准备和依赖安装

2.1 系统要求检查

首先创建环境检查脚本:

bash 复制代码
#!/bin/bash
# check_environment.sh

echo "检查系统环境..."

# 检查操作系统
if [ -f /etc/os-release ]; then
    . /etc/os-release
    OS=$NAME
    VER=$VERSION_ID
    echo "操作系统: $OS $VER"
else
    echo "警告: 无法检测操作系统版本"
fi

# 检查磁盘空间
echo "磁盘空间信息:"
df -h / /tmp /var

# 检查必要的工具
required_tools=("tar" "gzip" "mysql" "pg_dump" "curl")
for tool in "${required_tools[@]}"; do
    if command -v $tool &> /dev/null; then
        echo "✓ $tool 已安装"
    else
        echo "✗ $tool 未安装"
    fi
done

# 检查云存储工具
cloud_tools=("aws" "gsutil" "ossutil")
for tool in "${cloud_tools[@]}"; do
    if command -v $tool &> /dev/null; then
        echo "✓ $tool 已安装"
    else
        echo "✗ $tool 未安装 (可选)"
    fi
done

2.2 安装必要的软件包

根据不同的Linux发行版安装所需软件:

bash 复制代码
#!/bin/bash
# install_dependencies.sh

echo "安装备份所需的软件包..."

# 检测发行版
if [ -f /etc/redhat-release ]; then
    # CentOS/RHEL
    sudo yum update -y
    sudo yum install -y tar gzip mysql-server postgresql curl python3-pip
    
elif [ -f /etc/debian_version ]; then
    # Ubuntu/Debian
    sudo apt update
    sudo apt install -y tar gzip mysql-client postgresql-client curl python3-pip
    
else
    echo "不支持的Linux发行版"
    exit 1
fi

# 安装云存储CLI工具
echo "安装AWS CLI..."
pip3 install awscli --upgrade --user

echo "安装Google Cloud SDK..."
curl https://sdk.cloud.google.com | bash
exec -l $SHELL

echo "安装阿里云OSS工具..."
wget -O ossutil64 https://gosspublic.alicdn.com/ossutil/1.7.14/ossutil64
chmod 755 ossutil64
sudo mv ossutil64 /usr/local/bin/ossutil

3. 配置文件设置

创建主配置文件:

bash 复制代码
#!/bin/bash
# config/backup.conf

# 备份配置
BACKUP_DIR="/opt/backups"
LOG_DIR="/var/log/backups"
RETENTION_DAYS=30
COMPRESSION_LEVEL=6

# 网站文件配置
WEB_ROOT="/var/www/html"
EXCLUDE_PATTERNS=("*.log" "*.tmp" "cache/*" "tmp/*")

# 数据库配置
# MySQL
MYSQL_HOST="localhost"
MYSQL_PORT="3306"
MYSQL_USER="backup_user"
MYSQL_PASSWORD="your_secure_password"
MYSQL_DATABASES=("wordpress" "mydatabase" "application_db")

# PostgreSQL
PG_HOST="localhost"
PG_PORT="5432"
PG_USER="backup_user"
PG_PASSWORD="your_secure_password"
PG_DATABASES=("app_production" "analytics_db")

# 云存储配置
# AWS S3
AWS_BUCKET="my-backup-bucket"
AWS_REGION="us-east-1"

# Google Cloud Storage
GCS_BUCKET="my-backup-bucket"

# 阿里云OSS
OSS_BUCKET="my-backup-bucket"
OSS_ENDPOINT="oss-cn-hangzhou.aliyuncs.com"

# 通知配置
EMAIL_RECIPIENT="admin@example.com"
SLACK_WEBHOOK_URL="https://hooks.slack.com/services/your/webhook/url"

创建数据库用户配置脚本:

bash 复制代码
#!/bin/bash
# setup_database_users.sh

echo "设置数据库备份用户..."

# MySQL备份用户设置
mysql -u root -p <<EOF
-- 创建备份用户
CREATE USER IF NOT EXISTS 'backup_user'@'localhost' IDENTIFIED BY 'your_secure_password';

-- 授予必要权限
GRANT SELECT, LOCK TABLES, SHOW VIEW, PROCESS ON *.* TO 'backup_user'@'localhost';

-- 刷新权限
FLUSH PRIVILEGES;

-- 显示用户权限
SHOW GRANTS FOR 'backup_user'@'localhost';
EOF

# PostgreSQL备份用户设置
sudo -u postgres psql <<EOF
-- 创建备份用户
CREATE USER backup_user WITH PASSWORD 'your_secure_password';

-- 授予必要权限
ALTER USER backup_user WITH SUPERUSER;

-- 显示用户信息
\du backup_user
EOF

echo "数据库备份用户设置完成"

4. 核心备份脚本

创建主备份脚本:

bash 复制代码
#!/bin/bash
# website_backup.sh

# 加载配置
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "${SCRIPT_DIR}/config/backup.conf"

# 设置变量
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
BACKUP_NAME="backup_${TIMESTAMP}"
BACKUP_PATH="${BACKUP_DIR}/${BACKUP_NAME}"
LOG_FILE="${LOG_DIR}/backup_${TIMESTAMP}.log"

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 日志函数
log() {
    local level=$1
    local message=$2
    local timestamp=$(date '+%Y-%m-%d %H:%M:%S')
    echo -e "${timestamp} [${level}] ${message}" | tee -a "$LOG_FILE"
}

log_info() {
    log "INFO" "${BLUE}$1${NC}"
}

log_success() {
    log "SUCCESS" "${GREEN}$1${NC}"
}

log_warning() {
    log "WARNING" "${YELLOW}$1${NC}"
}

log_error() {
    log "ERROR" "${RED}$1${NC}"
}

# 错误处理函数
error_exit() {
    log_error "$1"
    send_notification "备份失败" "$1"
    exit 1
}

# 通知函数
send_notification() {
    local subject=$1
    local message=$2
    
    # 邮件通知
    if command -v mail &> /dev/null && [ -n "$EMAIL_RECIPIENT" ]; then
        echo "$message" | mail -s "Backup Alert: $subject" "$EMAIL_RECIPIENT"
    fi
    
    # Slack通知
    if command -v curl &> /dev/null && [ -n "$SLACK_WEBHOOK_URL" ]; then
        curl -X POST -H 'Content-type: application/json' \
            --data "{\"text\":\"*Backup Alert*: $subject\n$message\"}" \
            "$SLACK_WEBHOOK_URL" > /dev/null 2>&1
    fi
}

# 初始化备份环境
init_backup() {
    log_info "初始化备份环境..."
    
    # 创建目录
    mkdir -p "$BACKUP_DIR" "$LOG_DIR" "$BACKUP_PATH"
    
    # 检查目录权限
    if [ ! -w "$BACKUP_DIR" ]; then
        error_exit "备份目录不可写: $BACKUP_DIR"
    fi
    
    if [ ! -r "$WEB_ROOT" ]; then
        error_exit "网站目录不可读: $WEB_ROOT"
    fi
    
    log_success "备份环境初始化完成"
}

# 备份网站文件
backup_website_files() {
    log_info "开始备份网站文件..."
    
    local exclude_args=()
    for pattern in "${EXCLUDE_PATTERNS[@]}"; do
        exclude_args+=(--exclude="$pattern")
    done
    
    cd "$WEB_ROOT" || error_exit "无法进入网站目录: $WEB_ROOT"
    
    # 创建文件列表
    find . -type f > "${BACKUP_PATH}/file_list.txt"
    
    # 打包网站文件
    if tar czf "${BACKUP_PATH}/website_files.tar.gz" \
        "${exclude_args[@]}" \
        . > /dev/null 2>&1; then
        local size=$(du -h "${BACKUP_PATH}/website_files.tar.gz" | cut -f1)
        log_success "网站文件备份完成: ${size}"
    else
        error_exit "网站文件备份失败"
    fi
}

# 备份MySQL数据库
backup_mysql_databases() {
    log_info "开始备份MySQL数据库..."
    
    # 测试MySQL连接
    if ! mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SELECT 1" > /dev/null 2>&1; then
        log_warning "MySQL连接失败,跳过MySQL备份"
        return 1
    fi
    
    # 获取数据库列表
    local databases
    databases=$(mysql -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema|performance_schema|mysql|sys)")
    
    local success_count=0
    local total_count=0
    
    for db in $databases; do
        # 检查数据库是否在配置列表中
        if [[ " ${MYSQL_DATABASES[@]} " =~ " ${db} " ]] || [ ${#MYSQL_DATABASES[@]} -eq 0 ]; then
            ((total_count++))
            log_info "备份MySQL数据库: $db"
            
            if mysqldump -h "$MYSQL_HOST" -P "$MYSQL_PORT" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" \
                --single-transaction \
                --routines \
                --triggers \
                "$db" > "${BACKUP_PATH}/mysql_${db}.sql" 2>> "$LOG_FILE"; then
                
                # 压缩备份文件
                gzip "${BACKUP_PATH}/mysql_${db}.sql"
                ((success_count++))
                log_success "MySQL数据库备份完成: $db"
            else
                log_error "MySQL数据库备份失败: $db"
            fi
        fi
    done
    
    log_success "MySQL备份完成: ${success_count}/${total_count} 个数据库"
}

# 备份PostgreSQL数据库
backup_postgresql_databases() {
    log_info "开始备份PostgreSQL数据库..."
    
    # 设置密码
    export PGPASSWORD="$PG_PASSWORD"
    
    # 测试PostgreSQL连接
    if ! psql -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" -d postgres -c "SELECT 1" > /dev/null 2>&1; then
        log_warning "PostgreSQL连接失败,跳过PostgreSQL备份"
        return 1
    fi
    
    local success_count=0
    local total_count=0
    
    for db in "${PG_DATABASES[@]}"; do
        ((total_count++))
        log_info "备份PostgreSQL数据库: $db"
        
        if pg_dump -h "$PG_HOST" -p "$PG_PORT" -U "$PG_USER" \
            --verbose \
            --no-password \
            "$db" > "${BACKUP_PATH}/pgsql_${db}.sql" 2>> "$LOG_FILE"; then
            
            # 压缩备份文件
            gzip "${BACKUP_PATH}/pgsql_${db}.sql"
            ((success_count++))
            log_success "PostgreSQL数据库备份完成: $db"
        else
            log_error "PostgreSQL数据库备份失败: $db"
        fi
    done
    
    log_success "PostgreSQL备份完成: ${success_count}/${total_count} 个数据库"
}

# 创建备份清单
create_backup_manifest() {
    log_info "创建备份清单..."
    
    cat > "${BACKUP_PATH}/manifest.json" << EOF
{
    "backup_name": "${BACKUP_NAME}",
    "timestamp": "${TIMESTAMP}",
    "created_at": "$(date -Iseconds)",
    "components": {
        "website_files": "$(if [ -f "${BACKUP_PATH}/website_files.tar.gz" ]; then echo "true"; else echo "false"; fi)",
        "mysql_databases": "$(ls "${BACKUP_PATH}"/mysql_*.sql.gz 2>/dev/null | wc -l)",
        "postgresql_databases": "$(ls "${BACKUP_PATH}"/pgsql_*.sql.gz 2>/dev/null | wc -l)"
    },
    "system_info": {
        "hostname": "$(hostname)",
        "disk_usage": "$(df -h / | awk 'NR==2 {print $5}')"
    }
}
EOF
    
    log_success "备份清单创建完成"
}

# 压缩备份文件
compress_backup() {
    log_info "压缩备份文件..."
    
    cd "$BACKUP_DIR" || error_exit "无法进入备份目录"
    
    if tar czf "${BACKUP_NAME}.tar.gz" "$BACKUP_NAME" > /dev/null 2>&1; then
        local final_size=$(du -h "${BACKUP_NAME}.tar.gz" | cut -f1)
        log_success "备份文件压缩完成: ${final_size}"
        
        # 清理临时文件
        rm -rf "$BACKUP_PATH"
    else
        error_exit "备份文件压缩失败"
    fi
}

# 上传到云存储
upload_to_cloud() {
    log_info "开始上传到云存储..."
    
    local backup_file="${BACKUP_DIR}/${BACKUP_NAME}.tar.gz"
    
    # 上传到AWS S3
    if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
        log_info "上传到AWS S3..."
        if aws s3 cp "$backup_file" "s3://${AWS_BUCKET}/${BACKUP_NAME}.tar.gz" --region "$AWS_REGION" >> "$LOG_FILE" 2>&1; then
            log_success "上传到AWS S3完成"
        else
            log_error "上传到AWS S3失败"
        fi
    fi
    
    # 上传到Google Cloud Storage
    if command -v gsutil &> /dev/null && [ -n "$GCS_BUCKET" ]; then
        log_info "上传到Google Cloud Storage..."
        if gsutil cp "$backup_file" "gs://${GCS_BUCKET}/${BACKUP_NAME}.tar.gz" >> "$LOG_FILE" 2>&1; then
            log_success "上传到Google Cloud Storage完成"
        else
            log_error "上传到Google Cloud Storage失败"
        fi
    fi
    
    # 上传到阿里云OSS
    if command -v ossutil &> /dev/null && [ -n "$OSS_BUCKET" ]; then
        log_info "上传到阿里云OSS..."
        if ossutil cp "$backup_file" "oss://${OSS_BUCKET}/${BACKUP_NAME}.tar.gz" -e "$OSS_ENDPOINT" >> "$LOG_FILE" 2>&1; then
            log_success "上传到阿里云OSS完成"
        else
            log_error "上传到阿里云OSS失败"
        fi
    fi
}

# 清理旧备份
cleanup_old_backups() {
    log_info "清理旧备份文件..."
    
    local local_count=0
    local cloud_count=0
    
    # 清理本地备份
    find "$BACKUP_DIR" -name "backup_*.tar.gz" -type f -mtime +$RETENTION_DAYS | while read -r file; do
        rm -f "$file"
        ((local_count++))
    done
    
    # 清理云存储备份 (AWS S3示例)
    if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
        aws s3 ls "s3://${AWS_BUCKET}/" | grep "backup_" | while read -r date time size file; do
            local backup_date=$(echo "$file" | cut -d'_' -f2)
            local current_ts=$(date +%s)
            local backup_ts=$(date -d "${backup_date:0:8} ${backup_date:9:2}:${backup_date:11:2}:${backup_date:13:2}" +%s 2>/dev/null || echo 0)
            local age_days=$(( (current_ts - backup_ts) / 86400 ))
            
            if [ $age_days -gt $RETENTION_DAYS ]; then
                aws s3 rm "s3://${AWS_BUCKET}/$file"
                ((cloud_count++))
            fi
        done
    fi
    
    log_success "清理完成: 本地${local_count}个, 云存储${cloud_count}个备份文件"
}

# 生成备份报告
generate_report() {
    local end_time=$(date +%s)
    local duration=$((end_time - ${START_TIME}))
    
    cat > "${BACKUP_DIR}/backup_report_${TIMESTAMP}.txt" << EOF
备份报告
========

备份名称: ${BACKUP_NAME}
开始时间: $(date -d @${START_TIME} '+%Y-%m-%d %H:%M:%S')
结束时间: $(date -d @${end_time} '+%Y-%m-%d %H:%M:%S')
持续时间: ${duration} 秒

备份组件:
- 网站文件: $(if [ -f "${BACKUP_DIR}/${BACKUP_NAME}.tar.gz" ]; then echo "成功"; else echo "失败"; fi)
- MySQL数据库: $(ls "${BACKUP_DIR}" | grep "mysql_.*\.sql.gz" | wc -l) 个
- PostgreSQL数据库: $(ls "${BACKUP_DIR}" | grep "pgsql_.*\.sql.gz" | wc -l) 个

存储信息:
- 本地备份: ${BACKUP_DIR}/${BACKUP_NAME}.tar.gz
- 云存储: $(if [ -n "$AWS_BUCKET" ] || [ -n "$GCS_BUCKET" ] || [ -n "$OSS_BUCKET" ]; then echo "已上传"; else echo "未配置"; fi)

错误日志: $LOG_FILE
EOF
}

# 主函数
main() {
    START_TIME=$(date +%s)
    
    log_info "=== 开始备份任务 ==="
    
    # 执行备份流程
    init_backup
    backup_website_files
    backup_mysql_databases
    backup_postgresql_databases
    create_backup_manifest
    compress_backup
    upload_to_cloud
    cleanup_old_backups
    
    # 生成报告
    generate_report
    
    local end_time=$(date +%s)
    local duration=$((end_time - START_TIME))
    
    log_success "=== 备份任务完成 ==="
    log_success "总耗时: ${duration} 秒"
    
    # 发送成功通知
    send_notification "备份完成" "备份任务 ${BACKUP_NAME} 已完成,耗时 ${duration} 秒"
}

# 信号处理
trap 'log_error "备份被用户中断"; exit 1' INT TERM

# 执行主函数
main "$@"

5. 自动化部署脚本

创建安装和部署脚本:

bash 复制代码
#!/bin/bash
# deploy_backup_system.sh

set -e

echo "开始部署自动化备份系统..."

# 创建目录结构
echo "创建目录结构..."
sudo mkdir -p /opt/backups/{config,scripts,logs}
sudo mkdir -p /var/log/backups

# 复制脚本文件
echo "复制脚本文件..."
sudo cp website_backup.sh /opt/backups/scripts/
sudo cp config/backup.conf /opt/backups/config/
sudo cp check_environment.sh /opt/backups/scripts/

# 设置权限
echo "设置权限..."
sudo chmod +x /opt/backups/scripts/*.sh
sudo chmod 600 /opt/backups/config/backup.conf

# 设置配置文件权限
sudo chown root:root /opt/backups/config/backup.conf
sudo chmod 400 /opt/backups/config/backup.conf

# 创建备份用户
echo "创建备份用户..."
if ! id "backupuser" &>/dev/null; then
    sudo useradd -r -s /bin/bash -d /opt/backups backupuser
fi

# 设置目录所有权
sudo chown -R backupuser:backupuser /opt/backups
sudo chown -R backupuser:backupuser /var/log/backups

# 配置日志轮转
echo "配置日志轮转..."
sudo tee /etc/logrotate.d/backups > /dev/null <<EOF
/var/log/backups/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 644 backupuser backupuser
}
EOF

echo "部署完成!"

6. 定时任务配置

创建crontab配置:

bash 复制代码
#!/bin/bash
# setup_cron.sh

echo "配置定时任务..."

# 备份crontab
sudo cp /etc/crontab /etc/crontab.backup.$(date +%Y%m%d)

# 添加每日备份任务 (凌晨2点)
echo "0 2 * * * backupuser /opt/backups/scripts/website_backup.sh >> /var/log/backups/cron.log 2>&1" | sudo tee -a /etc/crontab

# 添加每周完整备份 (周日凌晨1点)
echo "0 1 * * 0 backupuser /opt/backups/scripts/website_backup.sh >> /var/log/backups/cron.log 2>&1" | sudo tee -a /etc/crontab

# 添加监控检查 (每小时)
echo "0 * * * * backupuser /opt/backups/scripts/check_environment.sh >> /var/log/backups/monitor.log 2>&1" | sudo tee -a /etc/crontab

# 重新加载cron
sudo systemctl reload crond

echo "定时任务配置完成"
echo "当前crontab配置:"
sudo crontab -l

7. 监控和验证脚本

创建备份验证脚本:

bash 复制代码
#!/bin/bash
# verify_backup.sh

source /opt/backups/config/backup.conf

echo "开始验证备份完整性..."

# 检查最新备份文件
latest_backup=$(ls -t ${BACKUP_DIR}/backup_*.tar.gz 2>/dev/null | head -1)

if [ -z "$latest_backup" ]; then
    echo "错误: 未找到备份文件"
    exit 1
fi

echo "验证备份文件: $latest_backup"

# 检查文件大小
file_size=$(du -h "$latest_backup" | cut -f1)
echo "备份文件大小: $file_size"

# 检查文件完整性
if tar tzf "$latest_backup" > /dev/null 2>&1; then
    echo "✓ 备份文件完整性检查通过"
else
    echo "✗ 备份文件损坏"
    exit 1
fi

# 检查备份内容
echo "备份内容:"
tar tzf "$latest_backup" | head -10

# 检查云存储备份
if command -v aws &> /dev/null && [ -n "$AWS_BUCKET" ]; then
    if aws s3 ls "s3://${AWS_BUCKET}/" | grep -q "$(basename $latest_backup)"; then
        echo "✓ 云存储备份验证通过"
    else
        echo "✗ 云存储备份不存在"
    fi
fi

echo "备份验证完成"

8. 恢复脚本

创建数据恢复脚本:

bash 复制代码
#!/bin/bash
# restore_backup.sh

source /opt/backups/config/backup.conf

show_usage() {
    echo "使用方法: $0 [选项]"
    echo "选项:"
    echo "  -f, --file FILE    指定备份文件"
    echo "  -d, --date DATE    按日期恢复 (格式: YYYYMMDD_HHMMSS)"
    echo "  -l, --list         列出可用备份"
    echo "  -w, --website      恢复网站文件"
    echo "  -m, --mysql        恢复MySQL数据库"
    echo "  -p, --postgresql   恢复PostgreSQL数据库"
    echo "  -a, --all          恢复所有内容"
}

list_backups() {
    echo "可用的备份文件:"
    ls -la ${BACKUP_DIR}/backup_*.tar.gz 2>/dev/null | while read file; do
        local size=$(du -h "$file" | cut -f1)
        local date=$(basename "$file" | sed 's/backup_\(.*\)\.tar\.gz/\1/')
        echo "  $date - $size - $file"
    done
}

restore_website() {
    local extract_dir="$1"
    echo "恢复网站文件..."
    
    if [ -f "${extract_dir}/website_files.tar.gz" ]; then
        sudo tar xzf "${extract_dir}/website_files.tar.gz" -C /tmp/website_restore
        echo "网站文件已提取到 /tmp/website_restore"
        echo "请手动将文件复制到目标目录"
    else
        echo "警告: 未找到网站文件备份"
    fi
}

restore_mysql() {
    local extract_dir="$1"
    echo "恢复MySQL数据库..."
    
    for sql_file in "${extract_dir}"/mysql_*.sql.gz; do
        if [ -f "$sql_file" ]; then
            local db_name=$(basename "$sql_file" | sed 's/mysql_\(.*\)\.sql\.gz/\1/')
            echo "恢复数据库: $db_name"
            
            gunzip -c "$sql_file" | mysql -h "$MYSQL_HOST" -u "$MYSQL_USER" -p"$MYSQL_PASSWORD"
            if [ $? -eq 0 ]; then
                echo "✓ 数据库恢复成功: $db_name"
            else
                echo "✗ 数据库恢复失败: $db_name"
            fi
        fi
    done
}

main() {
    local backup_file=""
    local restore_website=false
    local restore_mysql=false
    local restore_postgresql=false
    
    while [[ $# -gt 0 ]]; do
        case $1 in
            -f|--file)
                backup_file="$2"
                shift 2
                ;;
            -d|--date)
                local date="$2"
                backup_file="${BACKUP_DIR}/backup_${date}.tar.gz"
                shift 2
                ;;
            -l|--list)
                list_backups
                exit 0
                ;;
            -w|--website)
                restore_website=true
                shift
                ;;
            -m|--mysql)
                restore_mysql=true
                shift
                ;;
            -p|--postgresql)
                restore_postgresql=true
                shift
                ;;
            -a|--all)
                restore_website=true
                restore_mysql=true
                restore_postgresql=true
                shift
                ;;
            *)
                echo "未知选项: $1"
                show_usage
                exit 1
                ;;
        esac
    done
    
    if [ -z "$backup_file" ]; then
        echo "错误: 必须指定备份文件"
        show_usage
        exit 1
    fi
    
    if [ ! -f "$backup_file" ]; then
        echo "错误: 备份文件不存在: $backup_file"
        exit 1
    fi
    
    # 创建临时解压目录
    local temp_dir=$(mktemp -d)
    echo "解压备份文件到: $temp_dir"
    
    tar xzf "$backup_file" -C "$temp_dir"
    
    # 执行恢复操作
    if [ "$restore_website" = true ]; then
        restore_website "$temp_dir"
    fi
    
    if [ "$restore_mysql" = true ]; then
        restore_mysql "$temp_dir"
    fi
    
    # 清理临时文件
    rm -rf "$temp_dir"
    
    echo "恢复操作完成"
}

main "$@"

9. 使用说明和测试

创建测试脚本验证整个系统:

bash 复制代码
#!/bin/bash
# test_backup_system.sh

echo "开始测试备份系统..."

# 测试配置文件
if [ -f "/opt/backups/config/backup.conf" ]; then
    echo "✓ 配置文件存在"
else
    echo "✗ 配置文件缺失"
    exit 1
fi

# 测试主脚本
if [ -x "/opt/backups/scripts/website_backup.sh" ]; then
    echo "✓ 主脚本可执行"
else
    echo "✗ 主脚本不可执行"
    exit 1
fi

# 测试数据库连接
echo "测试数据库连接..."
if mysql -h localhost -u backup_user -p'your_secure_password' -e "SELECT 1" > /dev/null 2>&1; then
    echo "✓ MySQL连接正常"
else
    echo "✗ MySQL连接失败"
fi

# 执行测试备份
echo "执行测试备份..."
sudo -u backupuser /opt/backups/scripts/website_backup.sh

# 检查备份结果
if [ $? -eq 0 ]; then
    echo "✓ 备份测试成功"
else
    echo "✗ 备份测试失败"
    exit 1
fi

echo "备份系统测试完成"

10. 总结

本教程提供了一个完整的企业级网站和数据库备份解决方案,具有以下特点:

  1. 全面性:支持网站文件、MySQL、PostgreSQL数据库备份
  2. 可靠性:包含完整的错误处理和日志记录
  3. 自动化:支持定时任务和自动清理
  4. 多云支持:支持AWS S3、Google Cloud Storage、阿里云OSS
  5. 安全性:配置文件权限控制和敏感信息保护
  6. 可维护性:模块化设计和详细文档

通过按照本教程逐步实施,您可以建立一个生产级别的自动化备份系统,确保网站数据的安全性和可恢复性。

相关推荐
序安InToo24 分钟前
第6课|注释与代码风格
后端·操作系统·嵌入式
xyy12324 分钟前
C#: Newtonsoft.Json 到 System.Text.Json 迁移避坑指南
后端
洋洋技术笔记27 分钟前
Spring Boot Web MVC配置详解
spring boot·后端
JxWang0527 分钟前
VS Code 配置 Markdown 环境
后端
navms30 分钟前
搞懂线程池,先把 Worker 机制啃明白
后端
JxWang0531 分钟前
离线数仓的优化及重构
后端
Nyarlathotep011332 分钟前
gin01:初探gin的启动
后端·go
JxWang0532 分钟前
安卓手机配置通用多屏协同及自动化脚本
后端
JxWang0533 分钟前
Windows Terminal 配置 oh-my-posh
后端
SimonKing1 小时前
OpenCode AI编程助手如何添加Skills,优化项目!
java·后端·程序员