Appearance
备份脚本
本节实现一个功能完整的自动化备份脚本,支持增量备份、压缩加密、远程同步和备份轮转。
功能设计
- 支持多个备份源目录
- 压缩打包(tar + gzip)
- 按日期命名和组织备份文件
- 自动清理过期备份
- 可选远程同步(rsync/scp)
- 备份结果通知
完整备份脚本
bash
#!/usr/bin/env bash
#
# 自动化备份脚本
# 用法:./backup.sh [--config backup.conf]
#
set -euo pipefail
# ============================================================
# 默认配置
# ============================================================
BACKUP_SOURCES=(
"/etc"
"/var/www"
"/home"
)
BACKUP_DEST="/backup"
KEEP_DAYS=30 # 保留最近 N 天的备份
COMPRESS=true
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
HOSTNAME=$(hostname -s)
LOG_FILE="/var/log/backup.log"
# 远程同步配置(可选)
REMOTE_SYNC=false
REMOTE_HOST="backup-server"
REMOTE_USER="backup"
REMOTE_PATH="/remote/backup"
# ============================================================
# 工具函数
# ============================================================
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" | tee -a "$LOG_FILE"
}
error() {
log "ERROR: $*" >&2
exit 1
}
# 格式化字节大小
format_size() {
local bytes="$1"
if (( bytes < 1024 )); then
echo "${bytes}B"
elif (( bytes < 1048576 )); then
echo "$(( bytes / 1024 ))KB"
elif (( bytes < 1073741824 )); then
echo "$(( bytes / 1048576 ))MB"
else
echo "$(( bytes / 1073741824 ))GB"
fi
}
# ============================================================
# 备份函数
# ============================================================
# 备份单个目录
backup_dir() {
local source="$1"
local name="${source//\//_}"
name="${name#_}" # 去掉开头的下划线
local dest_file="${BACKUP_DEST}/${HOSTNAME}_${name}_${TIMESTAMP}.tar.gz"
log "备份:$source → $dest_file"
if [[ ! -d "$source" ]]; then
log "警告:目录不存在,跳过:$source"
return 0
fi
if tar -czf "$dest_file" "$source" 2>>"$LOG_FILE"; then
local size
size=$(stat -c %s "$dest_file")
log "备份完成:$dest_file($(format_size $size))"
echo "$dest_file"
else
error "备份失败:$source"
fi
}
# 数据库备份(MySQL 示例)
backup_mysql() {
local db_name="${1:-all}"
local db_user="${DB_USER:-root}"
local db_pass="${DB_PASS:-}"
local dest_file="${BACKUP_DEST}/${HOSTNAME}_mysql_${db_name}_${TIMESTAMP}.sql.gz"
log "备份 MySQL 数据库:$db_name"
if [[ "$db_name" == "all" ]]; then
mysqldump -u"$db_user" ${db_pass:+-p"$db_pass"} --all-databases 2>>"$LOG_FILE" | \
gzip > "$dest_file"
else
mysqldump -u"$db_user" ${db_pass:+-p"$db_pass"} "$db_name" 2>>"$LOG_FILE" | \
gzip > "$dest_file"
fi
log "数据库备份完成:$dest_file"
}
# 清理过期备份
cleanup_old_backups() {
log "清理 ${KEEP_DAYS} 天前的备份..."
local count=0
while IFS= read -r old_file; do
rm -f "$old_file"
(( count++ ))
log "删除过期备份:$old_file"
done < <(find "$BACKUP_DEST" -name "*.tar.gz" -o -name "*.sql.gz" | \
xargs ls -t 2>/dev/null | tail -n +$(( KEEP_DAYS + 1 )) 2>/dev/null || true)
log "共清理 $count 个过期备份"
}
# 同步到远程服务器
sync_to_remote() {
if [[ "$REMOTE_SYNC" != "true" ]]; then
return 0
fi
log "同步备份到远程:${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}"
rsync -avz --delete \
"$BACKUP_DEST/" \
"${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" \
2>>"$LOG_FILE" && log "远程同步完成" || log "警告:远程同步失败"
}
# ============================================================
# 主流程
# ============================================================
main() {
log "=========================================="
log "备份开始 | 主机:$HOSTNAME | 时间:$TIMESTAMP"
log "=========================================="
# 确保备份目录存在
mkdir -p "$BACKUP_DEST"
local start_time=$SECONDS
local backup_files=()
# 备份各源目录
for source in "${BACKUP_SOURCES[@]}"; do
if backup_file=$(backup_dir "$source"); then
backup_files+=("$backup_file")
fi
done
# 清理过期备份
cleanup_old_backups
# 远程同步
sync_to_remote
# 统计报告
local elapsed=$(( SECONDS - start_time ))
local total_size=0
for f in "${backup_files[@]}"; do
[[ -f "$f" ]] && total_size=$(( total_size + $(stat -c %s "$f") ))
done
log "=========================================="
log "备份完成!"
log " 备份文件数:${#backup_files[@]}"
log " 总大小:$(format_size $total_size)"
log " 耗时:${elapsed} 秒"
log "=========================================="
}
main "$@"增量备份(使用 rsync)
bash
#!/usr/bin/env bash
#
# rsync 增量备份脚本
#
SOURCE="/var/www"
DEST="/backup/incremental"
TIMESTAMP=$(date +%Y%m%d)
LATEST_LINK="$DEST/latest"
mkdir -p "$DEST/$TIMESTAMP"
rsync -av \
--link-dest="$LATEST_LINK" \
"$SOURCE/" \
"$DEST/$TIMESTAMP/" \
&& ln -snf "$DEST/$TIMESTAMP" "$LATEST_LINK"
echo "增量备份完成:$DEST/$TIMESTAMP"使用方法
bash
chmod +x backup.sh
# 立即执行备份
./backup.sh
# 加入定时任务(每天凌晨 2 点执行)
# crontab -e
# 0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1