简介
rsync
是一个功能强大的文件同步工具,支持高效的数据传输。它能够:
- 进行全量或增量备份。
- 支持增量备份,这意味着只有自上次备份以来发生变化的文件才会被传输。
- 提供
--link-dest
选项,支持硬链接(hard link),让你能高效地存储多个备份版本。
增量备份的关键:
rsync
通过硬链接(--link-dest
)避免重复存储没有变化的文件,显著节省存储空间。
增量备份是在前一次备份的基础上去做的
全量备份
rsync
全量备份:
sudo rsync -a --progress --delete /etc /bin /lib /usr /sbin /to/your/path/backup/system_backup/
-a
:归档模式- 递归复制目录:会复制整个目录,包括其中的子目录和文件。
- 保留文件属性:保持源文件的权限、时间戳、符号链接、用户和组信息等。
- 保留设备文件(对于特殊设备文件和管道等)。
- 保留符号链接:如果源是符号链接,
rsync
会保留链接本身,而不是复制链接指向的内容。
--progress
:显示文件传输的进度信息(每个文件的传输进度、已复制的数据量、传输速度等)。--delete
:删除目标目录中那些源目录中不存在的文件。常用于保持源和目标目录的完全同步。
脚本实现全量备份和增量备份
我们编写了一个 Bash 脚本来自动化全量和增量备份的过程,这里我仅保留最后3次的记录。
核心步骤如下:
#!/bin/bash
# 定义备份目录
BACKUP_DIR="/to/your/path/backup"
BACKUP_TYPE_DIR="$BACKUP_DIR/system_incremental"
# 定义系统文件备份目录
SYSTEM_DIRECTORIES="/etc /bin /lib /usr /sbin"
# 确保备份目录存在
mkdir -p $BACKUP_TYPE_DIR
# 获取当前日期(格式:YYYYMMDD)
CURRENT_DATE=$(date +%Y%m%d)
# 获取当天之前的所有备份(按日期分组)
PREVIOUS_BACKUPS=$(ls -d $BACKUP_TYPE_DIR/* | grep -v "$CURRENT_DATE" | sort)
# 对于今天之前的每一天,只保留最新的备份
if [ ! -z "$PREVIOUS_BACKUPS" ]; then
echo "Cleaning up previous backups..."
# 获取每一天的最新备份
DAYS=$(echo "$PREVIOUS_BACKUPS" | awk -F- '{print $1"-"$2"-"$3}' | sort | uniq)
for day in $DAYS; do
# 获取该天的所有备份
DAY_BACKUPS=$(echo "$PREVIOUS_BACKUPS" | grep "$day")
# 获取当天最新的备份(保留最新的一个)
KEEP_BACKUP=$(echo "$DAY_BACKUPS" | tail -n 1)
# 删除当天其他的备份
echo "$DAY_BACKUPS" | grep -v "$KEEP_BACKUP" | xargs sudo rm -rf
done
fi
# 获取最新的备份目录
LATEST_BACKUP=$(ls -d $BACKUP_TYPE_DIR/* | sort | tail -n 1)
# 如果没有任何备份,做全量备份
if [ -z "$LATEST_BACKUP" ]; then
NEW_BACKUP="$BACKUP_TYPE_DIR/full-$CURRENT_DATE-$(date +%H%M%S)"
sudo rsync -a --progress $SYSTEM_DIRECTORIES $NEW_BACKUP
else
# 做增量备份
NEW_BACKUP="$BACKUP_TYPE_DIR/inc-$CURRENT_DATE-$(date +%H%M%S)"
sudo rsync -a --progress --link-dest=$LATEST_BACKUP $SYSTEM_DIRECTORIES $NEW_BACKUP
fi
# 删除多余的旧备份(保留最近3天的每一天的最后一次备份)
cd $BACKUP_TYPE_DIR
ls -d * | sort | uniq -w 8 | head -n -3 | xargs sudo rm -rf
这里还有一个备份用户数据的, --exclude
是排除了 *.log
和 *.cache
这种文件减少错误:
#!/bin/bash
# 定义备份目录
BACKUP_DIR="/to/your/pathT7_Touch/backup"
- BACKUP_TYPE_DIR="$BACKUP_DIR/system_incremental"
+ BACKUP_TYPE_DIR="$BACKUP_DIR/user_incremental"
# 定义需要备份的目录(假设是 /home 和 /var)
FILES_TO_BACKUP="/home /var"
# 确保备份目录存在
mkdir -p $BACKUP_TYPE_DIR
# 获取当前日期(格式:YYYYMMDD)
CURRENT_DATE=$(date +%Y%m%d)
# 获取当天之前的所有备份(按日期分组)
PREVIOUS_BACKUPS=$(ls -d $BACKUP_TYPE_DIR/* | grep -v "$CURRENT_DATE" | sort)
# 对于今天之前的每一天,只保留最新的备份
if [ ! -z "$PREVIOUS_BACKUPS" ]; then
echo "Cleaning up previous backups..."
# 获取每一天的最新备份
DAYS=$(echo "$PREVIOUS_BACKUPS" | awk -F- '{print $1"-"$2"-"$3}' | sort | uniq)
for day in $DAYS; do
# 获取该天的所有备份
DAY_BACKUPS=$(echo "$PREVIOUS_BACKUPS" | grep "$day")
# 获取当天最新的备份(保留最新的一个)
KEEP_BACKUP=$(echo "$DAY_BACKUPS" | tail -n 1)
# 删除当天其他的备份
echo "$DAY_BACKUPS" | grep -v "$KEEP_BACKUP" | xargs sudo rm -rf
done
fi
# 获取最新的备份目录
LATEST_BACKUP=$(ls -d $BACKUP_TYPE_DIR/* | sort | tail -n 1)
# 如果没有任何备份,执行全量备份
if [ -z "$LATEST_BACKUP" ]; then
NEW_BACKUP="$BACKUP_TYPE_DIR/full-$CURRENT_DATE-$(date +%H%M%S)"
- sudo rsync -a --progress $SYSTEM_DIRECTORIES $NEW_BACKUP
+ sudo rsync -a --progress --exclude="*.log" --exclude="*.cache" $FILES_TO_BACKUP $NEW_BACKUP
else
# 做增量备份
NEW_BACKUP="$BACKUP_TYPE_DIR/inc-$CURRENT_DATE-$(date +%H%M%S)"
- sudo rsync -a --progress --link-dest=$LATEST_BACKUP $SYSTEM_DIRECTORIES $NEW_BACKUP
+ sudo rsync -a --progress --link-dest=$LATEST_BACKUP --exclude="*.log" --exclude="*.cache" $FILES_TO_BACKUP $NEW_BACKUP
fi
# 删除多余的旧备份(保留最近3天的每一天的最后一次备份)
cd $BACKUP_TYPE_DIR
ls -d * | sort | uniq -w 8 | head -n -3 | xargs sudo rm -rf
Bug
备份的内容太多了!咱也不知道是哪个的问题,所幸就不管它了~
设置服务随着开机且目标硬盘接入启动
这部分主要是为我的系统备份准备的
创建服务
在 /etc/systemd/system/
目录下创建一个 service
。比如:
sudo nano /etc/systemd/system/system_backup_after_mount.service
我这里是把脚本放到了
/usr/local/bin/
下,所以可以sudo全局调用。
[Unit]
Description=Run system_backup after mount
After=multi-user.target
RequiresMountsFor=/to/your/mount_path
[Service]
ExecStart=incremental_system_backup.sh
Type=oneshot
RemainAfterExit=false
[Install]
WantedBy=multi-user.target
After=multi-user.target
- 作用:
After
指定此服务在某个目标或服务之后启动。它只是设置启动顺序,并不意味着服务本身是依赖于目标。 - 示例:
After=multi-user.target
表示此服务会在系统达到multi-user.target
状态之后启动。multi-user.target
表示系统已进入多用户模式,用户可以登录并使用系统。 - 解释: 这意味着,只有在系统的多用户模式(即系统完成了基本的网络配置、登录等任务)启动之后,当前服务才会启动。
RequiresMountsFor=/to/your/mount_path
- 作用:
RequiresMountsFor=
是systemd
提供的一个特殊配置项,用来明确指定某个挂载点的依赖关系。它确保服务的执行依赖于指定路径的挂载。 - 示例:
RequiresMountsFor=/to/your/mount_path
表示当前服务依赖于/to/your/mount_path
路径的挂载。如果该路径没有被挂载,systemd
会阻止服务的启动,并在该挂载点完成挂载后再启动该服务。 - 解释: 这意味着,如果指定的挂载点(如
/to/your/mount_path
)没有被挂载,systemd
会等待直到该挂载点挂载完成,才能继续启动服务。这样可以防止服务在必要的挂载点未准备好时启动,避免出现错误。
设置服务自启
sudo systemctl enable system_backup_after_mount.service
设置服务定时执行
这部分是为我的用户数据做的,主要用到的是 定时器 和 服务。
创建服务
在 /etc/systemd/system/
目录下创建一个 service
。比如:
sudo nano /etc/systemd/system/user_backup.service
# /etc/systemd/system/user_backup.service
[Unit]
Description=Run user_backup after mount
After=multi-user.target
RequiresMountsFor=/to/your/mount_path
[Service]
ExecStart=incremental_user_backup.sh
Type=oneshot
RemainAfterExit=false
[Install]
WantedBy=multi-user.target
创建定时器
在 /etc/systemd/system/
目录下创建一个 timer
。比如:
sudo nano /etc/systemd/system/user_backup.timer
# /etc/systemd/system/user_backup.timer
[Unit]
Description=Run user_backup weekly
[Timer]
OnCalendar=weekly
Persistent=true
Unit=user_backup.service
[Install]
WantedBy=timers.target
OnCalendar=weekly
- 作用: 该字段定义了任务的调度时间。
- 示例:
OnCalendar=weekly
表示每周运行一次任务。 - 多种格式的示例:
OnCalendar=daily
:每天运行一次。OnCalendar=Mon *-*-* 12:00:00
:每周一中午12点运行。OnCalendar=*-01-01 00:00:00
:每年1月1日00:00运行。OnCalendar=2018-12-25 10:00:00
:在指定的日期和时间(2018年12月25日10:00)运行。
Persistent=true
- 作用: 如果系统在预定时间未能运行该定时器(例如,系统在指定时间关闭或暂停),该字段指示
systemd
是否在下次系统启动时执行该定时器任务。 - 示例:
Persistent=true
表示即使系统在预定的时间关闭,定时器也会在系统启动时运行,确保任务不遗漏。 - 如果为
false
或缺省: 系统不会执行错过的任务,只会在指定的下次时间运行。
Unit=user_backup.service
- 作用: 这个字段指定该定时器触发的服务单元。它指示
systemd
在定时器触发时运行哪个具体的服务。 - 示例:
Unit=user_backup.service
表示定时器触发时会运行名为user_backup.service
的服务单元。 - 常见用途: 可以指定任何有效的服务文件,如
backup.service
、cleanup.service
等。
WantedBy=timers.target
- 作用: 该字段定义了该定时器启用时所属的目标。目标是
systemd
中的一种单位类型,用来组织和管理多个服务或定时器。 - 示例:
WantedBy=timers.target
表示该定时器属于timers.target
,即系统定时器目标,这通常用于启用所有定时器相关的功能。 - 其他目标:
WantedBy=multi-user.target
:意味着服务将在multi-user
模式下运行。WantedBy=default.target
:将服务设置为默认启动。
设置定时器自动启动
sudo systemctl enable user_backup.timer
服务不需要自启,它会被定时器叫醒的~