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.sql | MySQL备份 |
mysql -u root -p db < backup.sql | MySQL恢复 |
find /backup -mtime +30 -delete | 清理旧文件 |