Linux备份与恢复

数据备份是系统管理的重要职责,良好的备份策略能在灾难发生时挽救数据。

备份策略

备份类型

类型说明优点缺点
完全备份备份所有数据恢复简单耗时、占用空间大
增量备份仅备份变化的数据快速、省空间恢复复杂
差异备份备份自上次完全备份后的变化恢复较快空间占用中等

推荐策略

周一:完全备份
周二-周日:增量备份
保留:4周完全备份 + 每日增量

tar归档备份

创建备份

# 创建压缩备份
tar -czvf backup.tar.gz /path/to/source/
 
# 选项说明
# -c: 创建归档
# -z: gzip压缩
# -j: bzip2压缩(更高压缩率)
# -v: 显示过程
# -f: 指定文件名
# -p: 保留权限
 
# 排除文件
tar -czvf backup.tar.gz --exclude='*.log' --exclude='tmp' /path/to/source/
 
# 按日期命名
tar -czvf backup-$(date +%Y%m%d).tar.gz /path/to/source/
 
# 备份整个系统(排除无关目录)
tar -czvpf /backup/system-$(date +%Y%m%d).tar.gz \
    --exclude='/proc' \
    --exclude='/sys' \
    --exclude='/dev' \
    --exclude='/tmp' \
    --exclude='/run' \
    --exclude='/mnt' \
    --exclude='/media' \
    --exclude='/lost+found' \
    --exclude='/backup' \
    /

恢复备份

# 解压到当前目录
tar -xzvf backup.tar.gz
 
# 解压到指定目录
tar -xzvf backup.tar.gz -C /target/path/
 
# 查看归档内容(不解压)
tar -tzvf backup.tar.gz
 
# 解压特定文件
tar -xzvf backup.tar.gz path/to/file
 
# 保留权限恢复
tar -xzvpf backup.tar.gz -C /

rsync增量同步

基本同步

# 本地同步
rsync -av /source/ /destination/
 
# 同步到远程
rsync -av /source/ user@remote:/backup/
 
# 从远程同步
rsync -av user@remote:/source/ /destination/
 
# 选项说明
# -a: 归档模式(保留权限、时间等)
# -v: 详细输出
# -z: 传输时压缩
# -h: 人类可读格式
# -P: 显示进度+支持断点续传

增量备份

# 使用--link-dest实现增量备份
rsync -av --link-dest=/backup/previous/ \
    /source/ /backup/current/
 
# 完整增量备份脚本
#!/bin/bash
SOURCE="/data/"
BACKUP_DIR="/backup"
DATE=$(date +%Y%m%d)
PREV_BACKUP=$(ls -d $BACKUP_DIR/*/ 2>/dev/null | tail -1)
 
rsync -av --link-dest=$PREV_BACKUP \
    $SOURCE $BACKUP_DIR/$DATE/
 
# 删除30天前的备份
find $BACKUP_DIR -maxdepth 1 -type d -mtime +30 -exec rm -rf {} \;

排除文件

# 排除特定文件
rsync -av --exclude='*.log' --exclude='tmp/' /source/ /dest/
 
# 使用排除文件
echo -e "*.log\ntmp/\n.cache/" > exclude.txt
rsync -av --exclude-from='exclude.txt' /source/ /dest/

删除目标多余文件

# 使目标与源完全一致(删除目标多余的文件)
rsync -av --delete /source/ /destination/
 
# 干运行(先测试)
rsync -av --delete --dry-run /source/ /destination/

数据库备份

MySQL/MariaDB

# 备份单个数据库
mysqldump -u root -p database_name > backup.sql
 
# 备份所有数据库
mysqldump -u root -p --all-databases > all_databases.sql
 
# 备份指定表
mysqldump -u root -p database_name table1 table2 > tables.sql
 
# 压缩备份
mysqldump -u root -p database_name | gzip > backup.sql.gz
 
# 恢复
mysql -u root -p database_name < backup.sql
gunzip < backup.sql.gz | mysql -u root -p database_name

PostgreSQL

# 备份单个数据库
pg_dump database_name > backup.sql
 
# 备份所有数据库
pg_dumpall > all_databases.sql
 
# 自定义格式(推荐)
pg_dump -Fc database_name > backup.dump
 
# 恢复
psql database_name < backup.sql
pg_restore -d database_name backup.dump

自动化备份脚本

完整备份脚本

#!/bin/bash
# /usr/local/bin/backup.sh
 
# 配置
SOURCE_DIRS=("/etc" "/home" "/var/www")
BACKUP_ROOT="/backup"
DATE=$(date +%Y%m%d)
LOG_FILE="/var/log/backup.log"
 
# 保留天数
KEEP_DAYS=30
 
log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_FILE
}
 
log "===== 开始备份 ====="
 
# 创建备份目录
BACKUP_DIR="$BACKUP_ROOT/$DATE"
mkdir -p $BACKUP_DIR
 
# 执行备份
for dir in "${SOURCE_DIRS[@]}"; do
    name=$(basename $dir)
    tar -czvf "$BACKUP_DIR/${name}.tar.gz" "$dir" 2>/dev/null
    if [ $? -eq 0 ]; then
        log "✓ $dir 备份成功"
    else
        log "✗ $dir 备份失败"
    fi
done
 
# 数据库备份
if command -v mysqldump &> /dev/null; then
    mysqldump -u backup_user -p'password' --all-databases | gzip > "$BACKUP_DIR/mysql.sql.gz"
    log "✓ MySQL备份完成"
fi
 
# 清理旧备份
find $BACKUP_ROOT -maxdepth 1 -type d -mtime +$KEEP_DAYS -exec rm -rf {} \;
log "清理超过 $KEEP_DAYS 天的旧备份"
 
# 磁盘空间检查
USAGE=$(df -h $BACKUP_ROOT | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $USAGE -gt 90 ]; then
    log "⚠ 警告: 备份目录使用率 ${USAGE}%"
fi
 
log "===== 备份完成 ====="

配置定时任务

# 编辑crontab
crontab -e
 
# 每天凌晨2点执行
0 2 * * * /usr/local/bin/backup.sh
 
# 每周日凌晨3点完全备份
0 3 * * 0 /usr/local/bin/backup-weekly.sh

远程备份

rsync over SSH

# 推送到远程
rsync -avz -e ssh /source/ user@remote:/backup/
 
# 使用SSH密钥认证
rsync -avz -e "ssh -i ~/.ssh/backup_key" /source/ user@remote:/backup/
 
# 限速传输(KB/s)
rsync -avz --bwlimit=1000 /source/ user@remote:/backup/

自动化远程备份

#!/bin/bash
# 使用SSH密钥实现无人值守远程备份
 
REMOTE_USER="backup"
REMOTE_HOST="backup.example.com"
REMOTE_DIR="/backup/server1"
LOCAL_DIR="/data"
SSH_KEY="/root/.ssh/backup_key"
 
rsync -avz --delete \
    -e "ssh -i $SSH_KEY -o StrictHostKeyChecking=no" \
    $LOCAL_DIR/ $REMOTE_USER@$REMOTE_HOST:$REMOTE_DIR/
 
# 发送通知
if [ $? -eq 0 ]; then
    echo "备份成功" | mail -s "备份报告" admin@example.com
fi

系统快照

LVM快照

# 创建快照
lvcreate -L 10G -s -n snap_root /dev/vg0/root
 
# 挂载快照
mkdir /mnt/snapshot
mount /dev/vg0/snap_root /mnt/snapshot
 
# 备份快照内容
tar -czvf /backup/snapshot.tar.gz /mnt/snapshot/
 
# 卸载并删除快照
umount /mnt/snapshot
lvremove /dev/vg0/snap_root

Btrfs快照

# 创建快照
btrfs subvolume snapshot /data /data/.snapshots/$(date +%Y%m%d)
 
# 列出快照
btrfs subvolume list /data
 
# 恢复快照
btrfs subvolume delete /data
btrfs subvolume snapshot /data/.snapshots/20260420 /data

灾难恢复

系统恢复步骤

# 1. 使用Live CD启动
 
# 2. 分区和格式化(如果需要)
fdisk /dev/sda
mkfs.ext4 /dev/sda1
 
# 3. 挂载分区
mount /dev/sda1 /mnt
 
# 4. 恢复备份
tar -xzvpf /media/usb/system-backup.tar.gz -C /mnt
 
# 5. 重新安装引导
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
chroot /mnt
grub-install /dev/sda
update-grub
exit
 
# 6. 重启
reboot

备份检查

验证备份完整性

# 验证tar归档
tar -tzvf backup.tar.gz >/dev/null && echo "归档完整"
 
# 验证压缩文件
gzip -t backup.tar.gz && echo "压缩文件完整"
 
# 对比文件
rsync -avn --delete /source/ /backup/ | grep -E "^deleting|^<f"

定期测试恢复

#!/bin/bash
# 测试恢复脚本
 
BACKUP_FILE="/backup/backup-$(date +%Y%m%d).tar.gz"
TEST_DIR="/tmp/restore-test"
 
mkdir -p $TEST_DIR
tar -xzvf $BACKUP_FILE -C $TEST_DIR
 
# 检查关键文件
if [ -f "$TEST_DIR/etc/passwd" ]; then
    echo "恢复测试成功"
    rm -rf $TEST_DIR
else
    echo "⚠ 恢复测试失败"
    exit 1
fi

快速参考

命令说明
tar -czvf backup.tar.gz /path创建压缩备份
tar -xzvf backup.tar.gz -C /path恢复备份
rsync -av /src/ /dest/同步目录
rsync -av --delete /src/ /dest/镜像同步
rsync -av --link-dest=/old/ /src/ /new/增量备份
mysqldump -u root -p db > backup.sqlMySQL备份
mysql -u root -p db < backup.sqlMySQL恢复
find /backup -mtime +30 -delete清理旧文件