贴一个自用的自动备份服务器数据的脚本

2026年06月14日 9点热度 0人点赞 0条评论

数据库账号为:backup,密码保存在:/etc/my.cnf.d/backup.conf ,文件内容为:

[client]
password="123456"

 

每天定时备份一次 crontab 脚本:

2 3 * * * /data/backup/backup_full.sh >> /var/log/backup_full.log 1>&1

 

备份脚本:backup_full.h

#!/bin/bash
set -euo pipefail

# ==================== 配置区(所有需要调整的参数均在此) ====================
# 备份根目录(绝对路径)
BACKUP_BASE="/data/backup"

# 备份保留天数(最终 .tar.gz 文件)
KEEP_DAYS=7

# 日志保留天数
LOG_RETENTION_DAYS=30

# MySQL 配置文件路径(存储密码)
MYSQL_CONFIG="/etc/my.cnf.d/backup.conf"

# MySQL 连接参数(用户名和主机,密码从配置文件读取)
MYSQL_OPTS="--defaults-extra-file=$MYSQL_CONFIG -h 127.0.0.1 -ubackup"
# mysqldump 额外选项(含事务、存储过程、事件、触发器)
MYSQL_DUMP_OPTS="$MYSQL_OPTS --single-transaction --routines --events --triggers"

# 需要备份的数据库列表
DATABASES=(
    wordpress
    weather_ical
    proftpd
    phpmyadmin
    platform_public
    platform_logs
    smsfilter
)

# 需要备份的网站目录(格式:"目标文件名:源目录路径")
WEB_SITES=(
    "weather_ical.tar:/www/m.wdeve.com/"
    "default.tar:/www/default/"
    "platform.tar:/www/platform/"
    "smsfilter.tar:/www/smsfilter.mdeve.com/"
)

# 需要备份的配置目录(格式:"目标文件名:源目录路径")
CONFIG_DIRS=(
    "etc.tar:/etc/"
    "php.etc.tar:/usr/local/php/etc/"
    "etc.nginx.tar:/usr/local/etc/"
    "frp.tar:/usr/local/frp/"
)

# 日志目录
LOG_DIR="/var/log/backup"

# ==================== 以下为自动变量,无需修改 ====================
BACKUP_DATE=$(date +%Y%m%d)
BACKUP_DIR="$BACKUP_DATE"
FINAL_TARBALL="$BACKUP_DATE.tar.gz"
LOG_FILE="$LOG_DIR/backup_$(date +%Y%m%d_%H%M%S).log"

mkdir -p "$LOG_DIR"
umask 077

# ==================== 日志函数 ====================
exec > >(tee -a "$LOG_FILE") 2>&1

log_info() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [INFO] $*"
}

log_error() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [ERROR] $*" >&2
}

log_success() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [SUCCESS] $*"
}

# ==================== 清理函数 ====================
cleanup() {
    local exit_code=$?
    if [ -n "${BACKUP_DIR:-}" ] && [ -d "$BACKUP_DIR" ] && [ "$BACKUP_DIR" != "/" ]; then
        log_info "Cleaning up temporary directory: $BACKUP_DIR"
        rm -rf "$BACKUP_DIR"
    fi
    if [ $exit_code -eq 0 ]; then
        log_success "Script finished successfully"
    else
        log_error "Script terminated with exit code $exit_code"
    fi
    wait
    exit $exit_code
}

trap cleanup EXIT
trap 'log_error "Command failed at line $LINENO"' ERR

# ==================== 磁盘空间检查 ====================
check_disk_space() {
    local required_mb=$1
    local available_kb=$(df --output=avail "$BACKUP_BASE" | tail -1)
    local available_mb=$((available_kb / 1024))
    if [ $available_mb -lt $required_mb ]; then
        log_error "Insufficient disk space in $BACKUP_BASE: ${available_mb}MB available, ${required_mb}MB required"
        exit 1
    fi
    log_info "Disk space check passed: ${available_mb}MB available"
}

# ==================== 开始备份 ====================
log_info "==================== Backup started ===================="
log_info "Backup date: $BACKUP_DATE"
log_info "Log file: $LOG_FILE"

mkdir -p "$BACKUP_BASE"
cd "$BACKUP_BASE"
check_disk_space 1024

if [ -d "$BACKUP_DIR" ]; then
    log_info "Removing existing directory: $BACKUP_DIR"
    rm -rf "$BACKUP_DIR"
fi

log_info "Creating backup directory: $BACKUP_DIR"
mkdir "$BACKUP_DIR"
cd "$BACKUP_DIR"

# ==================== 1. 备份数据库 ====================
log_info "Starting MySQL database backups..."
for db in "${DATABASES[@]}"; do
    log_info "Dumping database: $db"
    if mysqldump $MYSQL_DUMP_OPTS "$db" > "$db.sql"; then
        log_success "Database $db dumped successfully -> $db.sql"
    else
        log_error "Failed to dump database $db"
        exit 1
    fi
done
log_success "All databases backed up successfully"

# ==================== 2. 备份网站目录 ====================
log_info "Archiving website directories..."
for entry in "${WEB_SITES[@]}"; do
    tar_file="${entry%%:*}"
    src_dir="${entry#*:}"
    if [ ! -d "$src_dir" ]; then
        log_error "Source directory $src_dir does not exist"
        exit 1
    fi
    log_info "Creating archive: $tar_file from $src_dir"
    if tar --exclude='*.log*' -cvf "$tar_file" -C "$src_dir" . > /dev/null; then
        log_success "Archive created: $tar_file"
    else
        log_error "Failed to archive $src_dir"
        exit 1
    fi
done

# ==================== 3. 备份配置文件 ====================
log_info "Archiving configuration files..."
for entry in "${CONFIG_DIRS[@]}"; do
    tar_file="${entry%%:*}"
    src_dir="${entry#*:}"
    if [ ! -d "$src_dir" ]; then
        log_error "Source directory $src_dir does not exist"
        exit 1
    fi
    log_info "Creating archive: $tar_file from $src_dir"
    if tar -cvf "$tar_file" -C "$src_dir" . > /dev/null; then
        log_success "Archive created: $tar_file"
    else
        log_error "Failed to archive $src_dir"
        exit 1
    fi
done

# ==================== 4. 压缩整个备份目录 ====================
cd "$BACKUP_BASE"
log_info "Compressing backup directory: $BACKUP_DIR -> $FINAL_TARBALL"
if tar czvf "$FINAL_TARBALL" "$BACKUP_DIR" > /dev/null; then
    log_success "Compressed tarball created: $FINAL_TARBALL"
else
    log_error "Failed to create tarball"
    exit 1
fi

log_info "Removing temporary directory: $BACKUP_DIR"
rm -rf "$BACKUP_DIR"

# ==================== 5. 清理旧备份文件 ====================
log_info "Cleaning up old backups (older than $KEEP_DAYS days)..."
deleted_count=$(find "$BACKUP_BASE" -maxdepth 1 -name "*.tar.gz" -type f -mtime +$KEEP_DAYS -delete -print | wc -l)
if [ $deleted_count -gt 0 ]; then
    log_info "Removed $deleted_count old backup file(s)"
else
    log_info "No old backups to remove"
fi

# ==================== 6. 清理旧日志文件 ====================
log_info "Cleaning up old logs (older than $LOG_RETENTION_DAYS days)..."
deleted_logs=$(find "$LOG_DIR" -name "backup_*.log" -type f -mtime +$LOG_RETENTION_DAYS -delete -print | wc -l)
if [ $deleted_logs -gt 0 ]; then
    log_info "Removed $deleted_logs old log file(s)"
else
    log_info "No old logs to remove"
fi

log_success "Backup process completed successfully"
log_info "Final backup file: $BACKUP_BASE/$FINAL_TARBALL"
log_info "==================== Backup finished ===================="

exit 0

路灯

这个人很懒,什么都没留下

文章评论