Rsync 服务器
Rsync 工具
sync 与 rsync 的区别
sync: 内核级系统调用命令。Linux 系统为提升性能,文件修改通常先写入内存的缓冲区,sync 的唯一作用是将这些缓存数据强制刷写(Flush)到物理磁盘中,防止突发断电导致数据丢失,不涉及网络传输
rsync: 应用层文件同步工具。基于差异比对算法,在本地不同路径或网络节点之间进行增量或全量数据复制,解决的是文件生命周期管理与跨机备份问题
Rsync(Remote Synchronize)是一款开源的、快速的、多功能的远程数据同步备份工具,支持多种操作系统平台
Rsync 具有本地与远程两台主机之间的数据快速复制同步镜像、远程备份等功能,类似 scp 但优于 scp,还支持本地不同分区目录之间的全量及增量复制
Rsync 同步数据镜像时,通过 "quick check" 算法,仅同步大小或最后修改时间发生变化的文件或目录,也可根据权限、属主等属性变化进行同步,从而实现快速同步
| 命令 | 参数 | 机制 |
|---|---|---|
mkdir |
-p |
递归创建目录。自顶向下检查并创建多级路径,若目录已存在则不报错。 |
mkdir |
-m [MODE] |
在分配目录 inode 的瞬间直接写入指定的八进制权限,避免先创建再 chmod 引发的竞争条件安全漏洞。 |
cp |
-a |
归档模式(等同于 --preserve=all -d -r)。在本地完美复制硬链接、符号链接、ACL 权限、SELinux 安全标签和历史时间戳(mtime/atime)。 |
rsync |
-a |
归档模式(等同于 -rlptgoD)。负责保持标准目录结构、常规读写权限、文件修改时间。但会丢失硬链接关系、ACL 以及扩展属性 |
rsync |
-aHAX |
系统级全量克隆黄金组合。补充了硬链接(-H)、ACL 细粒度权限(-A)以及扩展属性/SELinux 安全上下文(-X)的完整保留能力 |
rsync |
-P / --partial |
激活断点续传。传输中断时保留未完成的隐藏临时文件。再次同步时利用差异比对算法仅请求发送缺失的数据块 |
关于文件元数据
每个文件在 Linux 底层都由一个 inode(索引节点) 来表示。inode 内部存储了除文件名之外的所有元数据
inode 核心字段
| 字段 | 说明 |
|---|---|
| File Type(文件类型) | 区分该节点是普通文件(-)、目录(d)、符号链接(l),还是底层物理设备(如硬盘 b、串口 c) |
| File Size(文件大小) | 记录文件占用数据的实际字节数(Byte) |
| Links Count(硬链接数) | 记录有多少个文件名同时指向这个相同的 inode;当计数归零时,系统才会真正释放磁盘空间 |
| Inode Number(inode 号) | 文件在当前文件系统分区中的唯一标识 |
| Blocks(磁盘块数) | 该文件实际占用了多少个 512 字节的物理扇区 |
| Extended Attributes(xattr,扩展属性) | 如 SELinux 安全标签,或用户自定义的隐藏 KV 数据 |
inode 时间戳
inode 中记录三类时间戳:mtime 、ctime 、atime
-
mtime (Modification Time, 修改时间)
文件内容发生改变时更新,如修改代码、写入日志
-
ctime (Change Time, 状态改动时间)
文件的元数据 (inode) 发生改变时更新,如修改权限、改名、新增硬链接
注意 :修改文件内容时,文件大小或 mtime 随之变化,inode 元数据也会改变,因此 mtime 改变时,ctime 必定跟着改变
-
atime (Access Time, 访问时间)
文件被读取 时更新(如使用
cat、grep,或执行某个可执行程序)
atime 与挂载优化
在现代 Linux 生产环境中,atime 的更新通常会被挂载优化。早期设计中,只要读取一次文件,系统就会立刻向硬盘写入一次 atime 更新------这带来严重的性能悖论:明明是只读操作,底层却触发物理写盘。在高并发的 Web 服务器或数据库场景下,大量读取会导致磁盘 I/O 被无意义的 atime 写入拖垮
现代 Linux 挂载文件系统时(参见 /etc/fstab),默认采用以下优化策略之一:
- relatime(系统默认):相对按需更新。仅当「上一次的 atime 已经比 mtime 更旧」,或「atime 已超过 24 小时未更新」时,本次读取才会真正触发写入
- noatime(高性能):完全禁止更新 atime;读取时内核跳过修改时间戳,以换取更好的读取性能
ctime 的不变性
ctime 是由 Linux 内核控制的「绝对诚实时间」。执行 cp -a 时,必须在目标磁盘上创建全新的 inode 并写入数据。新节点的创建、权限写入、所有者变更等动作都属于「修改了该节点的元数据」------内核一旦发现 inode 被动过,就会将当前系统时间强制写入 ctime。在这个世界上没有任何常规命令能够保持或克隆原文件的 ctime,即便是 root 权限下的 cp,也无法直接修改或伪造 ctime
rsync 命令
两种通信模式
- shell 模式:基于 SSH 服务传送
- daemon 模式:基于 rsyncd 服务传送
shell 模式
shell 模式基于 SSH 服务传送
安装软件包
客户端和服务端都需要安装 rsync:
bash
[root@client ~]# yum install -y rsync
[root@server ~]# yum install -y rsync
若通信双方有一方未安装 rsync,会出现如下报错:
text
bash: rsync: command not found
rsync: connection unexpectedly closed (0 bytes received so far) [sender]
rsync error: error in rsync protocol data stream (code 12) at io.c(226) [sender=3.1.3]
语法
bash
rsync [OPTION]... SRC DEST
rsync [OPTION]... SRC [USER@]HOST:DEST
rsync [OPTION]... [USER@]HOST:SRC DEST
常用选项
| 选项 | 说明 |
|---|---|
-n |
空运行,显示结果但不实际改变 |
-v |
显示详细输出 |
-a |
archive mode,等价于 -r -l -p -t -g -o -D |
-r |
递归同步整个文件夹 |
-l |
同步软链接 |
-p |
保留权限 |
-t |
保留时间戳 |
-g |
保留所属组 |
-o |
保留所有者 |
-D |
同步设备文件 |
-A |
同步时保留 ACL |
-X |
同步时保留 SELinux 内容(-a 不同步 ACL/SELinux) |
示例
bash
# 准备测试数据
[rich@client ~]$ mkdir backup
[rich@client ~]$ touch backup/file-{1..5}
# 首次同步
[rich@client ~]$ rsync -av backup root@server:
sending incremental file list
backup/
backup/file-1
backup/file-2
backup/file-3
backup/file-4
backup/file-5
sent 344 bytes received 115 bytes 918.00 bytes/sec
total size is 0 speedup is 0.00
# 再次同步(无变化)
[rich@client ~]$ rsync -av backup root@server:
sending incremental file list
sent 142 bytes received 17 bytes 318.00 bytes/sec
total size is 0 speedup is 0.00
# 更新部分文件时间戳后再同步
[rich@client ~]$ touch backup/file-{1,2}
[rich@client ~]$ rsync -av backup root@server:
sending incremental file list
backup/file-1
backup/file-2
sent 232 bytes received 55 bytes 574.00 bytes/sec
total size is 0 speedup is 0.00
# 删除 SRC 中文件,默认不会同步删除 DEST 中文件
# 使用 --delete 选项可同步删除 DEST 中对应文件
同步注意事项
- 文件访问时间、读写权限、文件内容等有任何变动,都会被视为已修改
- 目标目录下若文件比源目录还新,则不会同步
- 源路径末尾是否有斜杠含义不同:
- 有 / 结尾:只复制目录中的文件
- 无 / 结尾:复制目录本身及其中的文件
daemon 模式
daemon 模式需要服务器配置 rsync 服务。
语法
语法 1:源路径或目的路径的主机名后包含两个冒号
bash
rsync [OPTION]... SRC [USER@]HOST::DEST
rsync [OPTION]... [USER@]HOST::SRC DEST
语法 2 :rsync:// URL 格式,无需 SSH 服务
bash
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]
Rsync 服务
安装软件包
bash
[root@server ~]# yum install -y rsync-daemon
配置文件
rsync 配置文件为 /etc/rsyncd.conf,分为两部分:
- 全局部分 :为所有模块提供默认配置,可写在
[global]下([global]可省略) - 模块部分:同步目录配置,每个模块可有独立配置
ini
# 全局配置
[global]
# 指定监听 port 和 address
port = 873
address = server
# 指定保存 rsyncd 程序 pid 的文件
pid file = /var/run/rsyncd.pid
# 添加模块配置,例如 data 模块
[data]
# 同步目录的注释
comment = public data
# 同步目录的路径
path = /data
# 同步目录是否允许上传
# yes 代表不允许上传(只允许下载)
# no 代表可以上传和下载
read only = yes
# 同步目录是否允许下载
# yes 代表不允许下载(只允许上传)
# no 代表可以下载和上传
write only = yes
# 传送前是否 chroot 到同步目录,设置为 yes 更安全
use chroot = no
# 并发连接数
max connections = 200
# 控制并发连接数将使用该 lock file
lock file = /var/run/rsync.lock
# 指定保存 rsyncd 程序日志的文件
log file = /var/log/rsyncd.log
# 指定 rsyncd 程序日志 facility
syslog facility = local0
# 指定文件上传或下载时 user-owner(uid)和 group-owner(gid)
uid = rsync
gid = rsync
# 指定哪些客户端可以访问
hosts allow = 192.168.203.0/24
hosts deny = 0.0.0.0/32
# 如果 io 错误,跳过 delete 同步
ignore errors = yes
# 客户端向服务端查询模块列表时,是否显示该模块
list = false
# 客户端传故障时,强制断开客户端连接前的时间
timeout = 300
# 验证用户名,使用逗号或空格分隔
auth users = rsync
# 用户密码信息文件位置
secrets file = /etc/rsync.password
更多 rsyncd.conf 配置参考 rsyncd.conf(5)
准备同步目录
bash
[root@server ~]# mkdir -m 777 /rich
配置 rsync --- 不验证用户
客户端与 rsync 服务之间同步,既可以验证用户,也可以不验证用户。
bash
[root@server ~]# vim /etc/rsyncd.conf
添加如下配置:
ini
[rich]
comment = rich data
path = /rich
read only = no
启用服务
bash
# 配置防火墙
[root@server ~]# firewall-cmd --add-service=rsyncd
[root@server ~]# firewall-cmd --add-service=rsyncd --permanent
# 关闭 SELinux
[root@server ~]# setenforce 0
# 启用并启动服务
[root@server ~]# systemctl enable rsyncd --now
客户端测试
bash
# 上传
[rich@client ~]$ rsync -av backup server::rich
sending incremental file list
backup/
backup/file-1
backup/file-2
backup/file-3
backup/file-4
backup/file-5
sent 352 bytes received 115 bytes 934.00 bytes/sec
total size is 0 speedup is 0.00
[root@server ~]# ls /rich/backup/
file-1 file-2 file-3 file-4 file-5
# 下载
[rich@client ~]$ rsync -av server::rich/backup/file-1 file1
receiving incremental file list
file-1
sent 43 bytes received 92 bytes 270.00 bytes/sec
total size is 0 speedup is 0.00
[rich@client ~]$ ls file1
file1
配置 rsync --- 验证用户
添加如下配置:
ini
[rich]
path = /rich
read only = no
auth users = rsync
secrets file = /etc/rsyncd.secrets
创建用户凭据文件:
bash
[root@server ~]# echo 'rsync:redhat' > /etc/rsyncd.secrets
[root@server ~]# chmod 400 /etc/rsyncd.secrets
# 重启 rsyncd 服务
[root@server ~]# systemctl restart rsyncd
客户端测试
bash
# 服务端更新文件
[root@server ~]# echo hello world > /rich/backup/file-1
# 使用正确的用户名和密码同步
[rich@client ~]$ rsync -av rsync@server::rich/backup/file-1 file1
Password:
receiving incremental file list
file-1
sent 43 bytes received 108 bytes 100.67 bytes/sec
total size is 12 speedup is 0.08
[rich@client ~]$ cat file1
hello world
# 使用错误的用户名和密码同步
[rich@client ~]$ rsync -av rich@server::rich/backup/file-1 file1
Password: `redhat`
@ERROR: auth failed on module rich
rsync error: error starting client-server protocol (code 5) at main.c(1668) [Receiver=3.1.3]
# 客户端还可以使用非交互方式同步
[rich@client ~]$ echo redhat > rsyncd.secrets
[rich@client ~]$ chmod 400 rsyncd.secrets
[rich@client ~]$ rsync -av --password-file=./rsyncd.secrets rsync@server::rich/backup/file-1 file1