1. Rsync 介绍
Rsync (Remote Synchronization) 是一个功能强大的文件同步工具,以其高效的差异传输算法著称,广泛应用于备份、镜像和文件同步场景。
1.1. Rsync 作为客户端使用
把 Rsync 当客户端命令来用时它本质就是一个用来拷贝文本的工具,既可以在本地使用它来拷贝文件就像 cp 命令一样,也可以用它来进行远程传输就像 scp 那样。
与 cp 和 scp 命令的区别:
- Rsync 同时涵盖了 cp 与 scp,一条命令即可支持本地和远程复制。
- cp 或 scp 都是全量拷贝,而 Rsync 则是增量拷贝。
- 远程传输时,Rsync 支持 scp 所不具备的断点续传功能,一旦中途断掉重新执行命令不需要复制整个文件
- Rsync 灵活性和可配置性强
- Rsync 拥有大量的命令行选项,可以对传输过程进行精细控制,比如可以设定包含和排除规则来控制哪些文件需要被同步,也可以尽可能地保留符号链接、硬链接、权限、用户及组信息等文件属性。
1.2. Rsync 作为服务端使用
Rsync 客户端命令在进行远程传输时,支持两种协议,分别对应两种服务端:
- 使用 ssh 协议,对应的服务端服务是 sshd,此时服务端不需要启动 Rsync-daemon 服务。(默认使用 ssh 协议)
- 使用 Rsync 协议,对应的服务端服务是 Rsync-daemon,此时服务端需要启动 Rsync-daemon 服务。
使用 ssh 协议,则会与服务端的 sshd 建立会话:
# 基本语法
rsync [选项] 源路径 目标路径
# 示例
rsync -avz /local/path/ username@remotehost:/remote/path/ # 默认ssh协议,使用系统账号认证
Bash使用 Rsync 协议,则会与服务端的 Rsync -daemon 守护进程建立会话:
# 基本语法
rsync [选项] 源路径 目标路径
# 示例
rsync -avz /local/path/ rsync://remotehost::module/path
# module 是指 Rsync 守护进程(rsyncd)配置文件(rsyncd.conf)中定义的模块名称,它代表了远程服务器上某个特定的可访问目录或资源。
# /path 是模块根目录下的子路径
# 模块配置示例
[backup] # 模块名称为 "backup"
path = /data/backups # 对应的实际路径
comment = Backup Files # 描述
read only = yes # 只读
auth users = user1 # 授权用户
# 示例
rsync -avz /local/data/ rsync://example.com::backup/project/
# 这会将本地数据同步到远程服务器的 /data/backups/project/ 目录(假设 backup 模块配置的 path 是 /data/backups)
Bash对于大多数情况,特别是跨互联网传输,优先使用SSH协议。安全性更高,配置更简单。
1.3. Rsync 命令参数详解
基础语法:
rsync [选项] 源路径 目标路径
Bash常用参数详解:
- -v/–verbose:显示详细传输信息。
- -r/–recursive:递归同步目录。
- -l/–links:保留符号链接。
- -p/–perms:保留权限。
- -t/–times:保留修改时间。
- -n:模拟执行结果,通常用于执行命令前检查命令结果与预期是否相符。
- -a:归档模式(-rlptgoD),完整目录同步。
- -z:传输时压缩。
- -P:显示进度+断点续传。
- –delete:删除目标多余文件。
- –bwlimit=1000:限速1000KB/s。
- –exclude=”*.tmp”:排除特定文件。
- –backup:如果源文件与目标文件冲突,该选项可以确保不会直接覆盖掉,目标位置下的同名文件会被重命名默认~号结尾。
应用示例:
本地拷贝文件:
rsync /etc/passwd /test
rsync -r /etc/cron.d /test # 把文件夹cron.d拷贝到/test下
rsync -r /etc/cron.d/ /test # 把文件夹cron.d下的内容拷贝到/test下
Bash远程备份:
# 使用 ssh 协议
rsync -avz /data/ user@remote:/backups/
# 指定 ssh 端口
rsync -avz -e 'ssh -p 8888' source/ user@remote_host:/backups/
Bash目录差异对比(模拟运行):
rsync -avn --delete /src/ /dest/
# -n 模拟执行,显示差异不实际传输
Bash2. Rsync 实现增量备份
Rsync 除了源目录与目标目录直接比较外,Rsync 还支持使用 -link-dest 参数用来指定同步时的基准目录,即将源目录与基准目录之间变动的部分,同步到目标目录。
rsync -a --delete --link-dest /compare/path /source/path /target/path
# --link-dest 参数指定基准目录 /compare/path
# 将源目录 /source/path 与基准目 /compare/path 进行比較,找出改动的文件,将它们拷到目标目录 /target/path。
# 那些没变动的文件则会生成硬链接,硬链接指向上一个 /target/path 中的文件。这个命令的第一次备份时是全量备份,后面就都是增量备份了。
Bash增量备份示例:
# 模拟数据目录
mkdir data
echo 111 > data/1.txt
echo 222 > data/2.txt
# 第一次全量备份
mkdir bak
rsync -a --delete data/ bak/111/
# 改动数据目录
echo 333 > data/3.txt
# 第二次以第一次全量备份为基准目录进行增量备份
rsync -a --delete --link-dest ../111/ data/ bak/222/
# --link-dest 可以使用绝对路径和相对路径,其中相对路径是相对于目标目录的路径(不是当前目录)
# 改动数据目录
echo 666 >> data/1.txt
# 第三次以第二次增量备份为基准目录进行增量备份
rsync -a --delete --link-dest ../222 data/ bak/333/
Bash与传统的增量备份略有不同的是,rsync 的每次增量备份都会保留源目录中的全部文件,但是若文件较之上一次没有变化,则新备份中的文件只是创建了一个指向上一次对应文件的硬链接,这就保证了在不浪费空间的前提下保证了 rsyn 的增量 备份在恢复数据时只需要找到一份备份既可以恢复到指定的状态,这就使得其数据恢复过程的简洁性与完全备份一样了,同时会不会造成储存空间的浪费。
3. Rsync + innotify 实现实时同步
inotify 由 inotify-tools 包提供。在安装 inotify-tools 之前,请确保内核版本高于 2.6.13,且在 /proc/sys/fs/inotify 目录下有以下三项,这表示系统支持 inotify 监控。
ll /proc/sys/fs/inotify
-rw-r--r-- 1 root root 0 Jun 27 10:57 max_queued_events
-rw-r--r-- 1 root root 0 Jun 27 10:57 max_user_instances
-rw-r--r-- 1 root root 0 Jun 27 10:57 max_user_watches
# max_queued_events: 调用 ginotify_init 时分配到 inotify instance 中可排队的 event 数的最大值,超出值时的事件被丢弃,但会触发队列溢出 QOVERFLOW 事件。
# max_user_instances: 每一个 real user 可创建的 inotify instances 数量的上限。
# max_user_watches: 每个 inotify 实例相关联的 watches 的上限,即每个 inotify 实例可监控的最大目录、文件数量。如果监控的文件数目巨大,需要根据情况适当增加此值。
Bash安装 :
# 在源服务器执行
sudo apt-get install rsync inotify-tools # Ubuntu/Debian
sudo yum install rsync inotify-tools # RHEL/CentOS
# inotify-tools 工具只提供了两个命令
rpm -ql inotify-tools | grep bin/
/usr/bin/inotifywait
/usr/bin/inotifywatch
# inotifywait 命令用于等待文件发生变化,所以可以实现监控(watch)的功能,该命令是 inotify 的核心命令。
# inotifywatch 用于收集文件系统的统计数据,例如发生了多少次 inotify 事件,某文件被访问了多少次等等,一般用不上。
Bash配置SSH免密登录(从源服务器到目标服务器):
ssh-keygen -t rsa
ssh-copy-id user@目标服务器IP
Bash编写监控脚本(源服务器):
创建 /usr/local/bin/inotify_rsync.sh
:
#!/bin/bash
# 同步参数
SOURCE_DIR="/data/source" # 监控的源目录
DEST_IP="192.168.1.100" # 目标服务器IP
DEST_USER="syncuser" # 目标服务器用户名
DEST_DIR="/data/backup" # 目标目录
LOG_FILE="/var/log/inotify_rsync.log"
# 排除文件模式
EXCLUDE="--exclude='*.tmp' --exclude='*.swp'"
# 初始化首次完整同步
echo "$(date) 开始初始同步" >> $LOG_FILE
rsync -avz --delete $EXCLUDE $SOURCE_DIR/ $DEST_USER@$DEST_IP:$DEST_DIR/
echo "$(date) 初始同步完成" >> $LOG_FILE
# 开始inotify监控
inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w%f %e' \
-e modify,delete,create,attrib,move $SOURCE_DIR | while read date time file event
do
# 记录事件
echo "$date $time $file $event" >> $LOG_FILE
# 根据事件类型处理
case $event in
MODIFY|CREATE|MOVE*|ATTRIB)
rsync -avz --delete $EXCLUDE $SOURCE_DIR/ $DEST_USER@$DEST_IP:$DEST_DIR/ >> $LOG_FILE 2>&1
;;
DELETE)
rsync -avz --delete $EXCLUDE $SOURCE_DIR/ $DEST_USER@$DEST_IP:$DEST_DIR/ >> $LOG_FILE 2>&1
;;
esac
done
Bashinotifywait 命令参数:
- 基础监控参数
- -m:持续监控而非单次运行
- -r:递归监控子目录
- -q:减少不必要输出
- -e:指定监控的事件类型
- 事件类型参数(-e 组合使用)
- access:文件被读取
- modify:文件内容被修改
- attrib:元数据变更(权限/时间戳)
- close_write:可写文件关闭后
- close_nowrite:只读文件关闭后
- open:文件被打开
- moved_to:文件移入监控目录
- moved_from:文件移出监控目录
- move:文件移动(包括目录内重命名)
- create:新建文件/目录
- delete:文件/目录被删除
- delete_self:监控项本身被删除
- unmount:文件系统卸载
- 输出控制参数
- –format:自定义输出格式,示例:
%w%f %e
→ “/test/file CREATE”%w
:监控目录名%f
:触发事件的文件名(目录事件为空)%e
:事件类型%T
:时间(需配合--timefmt
)
- –timefmt:时间格式(需配合
%T
),示例:%Y-%m-%d %H:%M:%S - –csv:CSV格式输出,示例:”/test”,”file”,”CREATE”
- –format:自定义输出格式,示例:
设置脚本权限:
chmod +x /usr/local/bin/inotify_rsync.sh
Bash配置系统服务(可选):
创建 /etc/systemd/system/inotify_rsync.service
:
[Unit]
Description=Inotify Rsync Service
After=network.target
[Service]
User=root
ExecStart=/usr/local/bin/inotify_rsync.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Bash启用服务:
systemctl daemon-reload
systemctl enable inotify_rsync
systemctl start inotify_rsync
Bash