不少同学在安装上总会出现这样那样的问题,不是不兼容就是因为其他的因素影响了安装的进度,本章节主要讲解安装以及rsync的传输方式与工作模式。
## 三 安装
注意,传输的双方都必须安装 rsync
```
yum install rsync -y
```
## 四 rsync的传输方式与工作模式
### 4.1 两种传输方式
```
1.pull 拉-> 下载
客户端将服务器上的数据下载到本地服务器
问题:如果客户端过多,会对服务端造成压力过大
2.push 推-> 上传
客户端将本地数据上传到服务器
问题:如果客户端过多,上传速度会受到带宽影响,很慢
```
### 4.2 两种工作模式
#### 4.2.1 本地模式
```bash
1、语法:
命令 选项 源数据 目标地址
rsync [OPTION]... SRC [SRC]... DEST
2、常用选项:rsync支持一百多个选项,所以此处只介绍几个常用选项
-a --archive :归档模式,表示递归传输并保持文件属性。等同于"-rtopgDl"。
-v :显示rsync过程中详细信息。可以使用"-vvvv"获取更详细信息。
-z :传输时进行压缩提高效率。
-R :使用相对路径
3、类似于cp命令,又不同于cp
(1)、cp命令只是本地复制,每次cp都会用源文件内容覆盖新文件,所以cp命令会修改文件时间属性,
(2)、rsync可本地可远程,首次rsync与cp一样,后续rsync会对比两个文件的不同,只传输文件更新的部分,如果未更新,则rsync不会修改文件任何属性
4、注意:源路径如果是一个目录的话,带上尾随斜线和不带尾随斜线是不一样的,不带尾随斜线表示的是整个目录包括目录本身,带上尾随斜线表示的是目录中的文件,不包括目录本身,这一点本地模式与远程模式均适用
```
示例1: 拷贝文件
```bash
[root@local ~]# rsync /etc/passwd /test
```
示例2:拷贝文件夹,-r,验证源路径带/后缀与不带后缀的两种情况
```bash
[root@local ~]# rsync -r /etc/cron.d /test # 把文件夹cron.d拷贝到/test下
[root@local ~]# rsync -r /etc/cron.d/ /test # 把文件夹cron.d下的内容拷贝到/test下
```
实例3:拷贝文件夹,-R,使用相对目录
```bash
[root@local ~]# mkdir -p /src/aaa/bbb/ccc
[root@local ~]# mkdir /dst
[root@local ~]#
[root@local ~]# rsync -r /src/aaa/bbb/ccc /dst/
[root@local ~]# ls /dst/
ccc
[root@local ~]#
[root@local ~]# rm -rf /dst/*
[root@local ~]# rsync -r -R /src/aaa/bbb/ccc /dst/
[root@local ~]# ls /dst/
src
[root@local ~]# rm -rf /dst/*
[root@local ~]# rsync -r -R /src/./aaa/bbb/ccc /dst/
[root@local ~]# ls /dst/
aaa
[root@local ~]# rm -rf /dst/*
[root@local ~]# rsync -r -R /src/aaa/./bbb/ccc /dst/
[root@local ~]# ls /dst/
bbb
[root@local ~]#
```
实例3:--backup选项,对目标目录下已经存在的文件做一个备份
```bash
[root@remote ~]# mkdir /egon111
[root@remote ~]# mkdir /egon222
[root@remote ~]#
[root@remote ~]# echo 111 > /egon111/1.txt
[root@remote ~]# echo 222 > /egon111/2.txt
[root@remote ~]# echo 333 > /egon111/3.txt
[root@remote ~]#
[root@remote ~]# echo 666 > /egon222/1.txt
[root@remote ~]# echo 888 > /egon222/2.txt
[root@remote ~]#
[root@remote ~]# rsync -r --backup /egon111/ /egon222/
[root@remote ~]# ll /egon222/
总用量 20
-rw-r--r--. 1 root root 4 4月 16 13:12 1.txt
-rw-r--r--. 1 root root 4 4月 16 13:11 1.txt~
-rw-r--r--. 1 root root 4 4月 16 13:12 2.txt
-rw-r--r--. 1 root root 4 4月 16 13:11 2.txt~
-rw-r--r--. 1 root root 4 4月 16 13:12 3.txt
[root@remote ~]#
[root@remote ~]# mkdir /egon222/bak
[root@remote ~]# rsync -r --backup --backup-dir=/egon222/bak /egon111/ /egon222/
[root@remote ~]# ls /egon222/bak/
1.txt 2.txt
[root@remote ~]# tree /egon222/
/egon222/
├── 1.txt
├── 2.txt
├── 3.txt
└── bak
├── 1.txt
└── 2.txt
```
这样在目标目录下,已存在的文件就被做一个备份,备份文件默认使用"~"做后缀,可以使用"--suffix"指定备份后缀,例如
```bash
[root@remote ~]# rsync -r --backup --suffix=".bak" /egon111/ /egon222/
```
可以使用"--backup-dir"指定备份文件保存路径,但要求保存路径必须存在,指定备份路径后,默认将不会加备份后缀,除非使用"--suffix"显式指定后缀,如"--suffix=~"。
```bash
[root@remote ~]# mkdir /egon222/bak
[root@remote ~]# rsync -r --backup --backup-dir=/egon222/bak /egon111/ /egon222/
[root@remote ~]# ls /egon222/bak/
1.txt 2.txt
[root@remote ~]# tree /egon222/
/egon222/
├── 1.txt
├── 2.txt
├── 3.txt
└── bak
├── 1.txt
└── 2.txt
```
示例4:
```
=======> 准备文件
[root@www ~]# echo 666 > egon.txt
[root@www ~]# stat egon.txt
......
最近改动:2021-04-08 20:00:10...
=======> cp每次拷贝都是用新的覆盖旧的,即每次都是全量
[root@www ~]# # 首次拷贝->全量
[root@www ~]# cp -a egon.txt egon111.txt
[root@www ~]# stat egon111.txt
......
最近改动:2021-04-08 20:00:20... ---> 改变
[root@www ~]#
[root@www ~]#
[root@www ~]#
[root@www ~]# # 第二次拷贝->仍是全量
[root@www ~]# \cp -a egon.txt egon111.txt # 加\开头取消默认提示
[root@www ~]# stat egon111.txt
......
最近改动:2021-04-08 20:00:30... ---> 改变
=======> rsync首次拷贝为全量,后续拷贝如果参照的源内容不变,则不覆盖目标文件
[root@www ~]# # 首次拷贝->全量
[root@www ~]# rsync -az egon.txt egon222.txt
[root@www ~]# stat egon222.txt
......
最近改动:2021-04-08 20:00:40... ---> 改变
[root@www ~]#
[root@www ~]#
[root@www ~]#
[root@www ~]# # 第二次拷贝->检测到源文件没有发生变动,则不会覆盖目标文件
[root@www ~]# rsync -az egon.txt egon222.txt
[root@www ~]# stat egon222.txt
......
最近改动:2021-04-08 20:00:40... ---> 不变
[root@www ~]#
[root@www ~]#
[root@www ~]#
[root@www ~]# # 第三次拷贝->检测到源文件没有发生变动,则不会覆盖目标文件
[root@www ~]# rsync -az egon.txt egon222.txt
[root@www ~]# stat egon222.txt
......
最近改动:2021-04-08 20:00:40... ---> 不变
```
其他选项
```bash
# 0、选项-c、--checksum改变rsync的检查方式
默认情况下,rsync基于"quick check"算法只检查文件的大小和最后修改日期是否发生变化,如果发生变化,就重新传输;当然,也可以通过在rsync命令行中指定某些选项来改变quick check的检查模式,比如"--size-only"选项表示"quick check"将仅检查文件大小不同的文件作为待传输文件。
使用-c参数以后,则通过判断文件内容的校验和,决定是否重新传输,增强了数据传输的可靠性但降低了效率,是否使用该选项呢?如果是私网内部传输,网络通常可控且较为稳定,文件完整性通常不会有问题,不需要加-c选项,如果是传到外网,网络不可控且不够稳定,可以考虑加上-c选项增强可靠性,此时需要付出的代价就是效率的降低,用不用请自行斟酌
rsync支持非常多的选项
一些选项控制检查的模式(如-c、--size-only等)、一些选项控制文件同步的模式(例如--delete等)
检查模式决定了哪些文件需要被同步
文件同步模式决定了在文件确定要被同步后、同步过程发生之前要做的额外工作
相对来说,为rsync手动指定同步模式的选项更常见一些,只有在有特殊需求时才指定检查模式,因为大多数检查模式选项都可能会影响rsync的性能,例如上面所述-c选项
# 1、选项-n
如果不确定 rsync 执行后会产生什么结果,可以先用`-n`或`--dry-run`参数模拟执行的结果。
rsync -anv source/ destination
上面命令中,-n参数模拟命令执行的结果,并不真的执行命令。-v参数则是将结果输出到终端,这样就可以看到哪些内容会被同步。
# 2、选项--delete
如果要使得目标目录成为源目录的镜像副本,则必须使用`--delete`参数,这将删除只存在于目标目录、不存在于源目录的文件,也就是"多则删之,少则补之"。
[root@www ~]# echo 111 > /aaa/1.txt
[root@www ~]# echo 222 > /aaa/2.txt
[root@www ~]# echo 333 > /aaa/3.txt
[root@www ~]# echo 444 > /bbb/4.txt
[root@www ~]#
[root@www ~]#
[root@www ~]#
[root@www ~]# rsync -az --delete /aaa/ /bbb/
[root@www ~]# ls /bbb/
1.txt 2.txt 3.txt
# 3、选项--exclude
有时,我们希望同步时排除某些文件或目录,这时可以用--exclude参数指定排除模式。
$ rsync -av --exclude='*.txt' source/ destination
或者
$ rsync -av --exclude '*.txt' source/ destination
上面命令排除了所有 TXT 文件。
注意,rsync 会同步以"点"开头的隐藏文件,如果要排除隐藏文件,可以这样写--exclude=".*"。
如果要排除source/下某个子目录里面的所有文件,但不希望排除该子目录本身,可以写成下面这样。
$ rsync -av --exclude 'dir1/*' source/ destination
多个排除模式,可以用多个--exclude参数。
$ rsync -av --exclude 'file1.txt' --exclude 'dir1/*' source/ destination
多个排除模式也可以利用 Bash 的大扩号的扩展功能,只用一个--exclude参数。
$ rsync -av --exclude={'file1.txt','dir1/*'} source/ destination
如果排除模式很多,可以将它们写入一个文件,每个模式一行,然后用--exclude-from参数指定这个文件。
$ rsync -av --exclude-from='exclude-file.txt' source/ destination
# 4、选项--include
用来指定必须同步的文件模式,往往与--exclude结合使用。
$ rsync -av --include="[0-9].txt" --exclude='*' source/ destination
上面命令指定同步时,排除所有文件,但是会包括1.txt、2.txt等文件,注意--include必须在--exclude之前
```
#### 4.2.2 远程模式
传输时需要认证远程主机的账号密码,有两种认证方式:ssh认证与守护进程rsync-daemon认证
```bash
# 1、ssh协议
(1)在本地与目标主机都安装rsync
(2)远程主机要打开sshd服务
(3)需要用到的账号是远程主机可登录系统账号---》不安全
(4)不受目录限制-------------------------》不安全
# 2、rsync协议
(1)在本地与目标主机都安装rsync
(2)远程主机要打开rsync守护进程
rsync --daemon
或
systemctl start rsyncd
(3)用到的是虚拟账号,虚拟账号对应的是配置文件中uid的权限,例如:uid=rsync
虚拟账号egon------->远端主机真实存在的系统账号rsync
(4)用的是模块名-》具体的目录
```
##### 4.2.2.1 远程模式之SSH认证
**基于ssh协议:rsync 默认使用 SSH 进行远程登录和数据传输,详细地说,rsync 在传输数据之前,会先与远端进行一次 ssh 登录认证(采用的是系统账号),因此需要目标主机事先开启ssh服务。**
语法:语法类似于scp命令,但备份方案不同于scp(scp 与 cp一样,每次都是全量)
```
# 拉取
命令 选项 远程用户@远程主机:远程的目录作为源 本地作为目标
rsync [OPTION] [USER@]HOST:SRC [DEST]
# 推送
命令 选项 本地数据作为源 远程用户@远程主机:远程的目录作为目标
rsync [OPTION] SRC [SRC]... [USER@]HOST:DEST
```
示例1:拉取
```python
[root@www ~]# rsync -avz root@192.168.12.17:/data /bak/
......
[root@www ~]# ls /bak/
data
[root@www ~]# 可以用stat命令查看一下最近改动时间,然后再次执行下行命令
[root@www ~]# rsync -avz root@192.168.12.17:/data /bak/
[root@www ~]# 此时用stat命令查看一下最近改动时间,与上一次完全相同
```
示例2:推送
```
[root@www ~]# rsync -avz /bak root@192.168.12.17:/data/ # 推送
```
由于早期 rsync 不使用 SSH 协议,需要用`-e`参数指定协议,后来才改的。所以,下面`-e ssh`可以省略。
```bash
$ rsync -av -e ssh source/ user@remote_host:/destination
```
但是,如果 ssh 命令有附加的参数,则必须使用`-e`参数指定所要执行的 SSH 命令。
```bash
$ rsync -av -e 'ssh -p 8888' source/ user@remote_host:/destination
```
上面命令中,`-e`参数指定 SSH 使用2234端口。
##### 4.2.2.2 远程模式之守护进程认证
1) 守护进程模式之rsync协议
```bash
守护进程模式其实也是一种远程模式,只不过采用的是rsync协议传输,
若想采用rsync协议传输,则需要远程主机也安装rsync,并启动rsync守护进程,此时不需要依赖远程主机的sshd服务
```
2)为什么使用守护进程模式
```
1.基于ssh的认证,传输时会使用系统用户和密码,不安全,而守护进程模式使用的是虚拟用户和虚拟密码
2.当使用普通用户传输文件时会出现权限不足的情况,而守护进程模式可以解决这个问题
```
3)如何使用rsync协议传输
在传输时,如果未指定协议,则默认用ssh协议,指定使用rsync协议的方式有两种
```bash
# 方式一:rsync://协议(默认端口873)
$ rsync -av source/ rsync://192.168.12.66/module/destination
# 方式二:远程目标前面使用连续两个冒号
$ rsync -av source/ 192.168.12.66::module/destination
完整语法:
Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
若远程主机修改了rsync守护进程的端口,那么在本机应该这么做
$ rsync -av source/ rsync://192.168.12.66:879/module/destination # 可以指定端口
```
注意,上面地址中的`module`并不是实际路径名,而是 rsync 守护程序指定的一个资源名,由管理员分配。
**守护进程模式搭建**
I:环境准备
| 主机 | IP | 角色 |
| ---- | ------------- | ----------- |
| 本地 | 192.168.12.17 | rsync客户端 |
| 远程 | 192.168.12.39 | rsync服务端 |
```bash
本地与远程均执行下述两条命令
setenforce 0
iptables -F
```
II:安装rsync(本地和远程主机都要装)
```bash
[root@remote ~]# yum install rsync -y
```
III:在远程主机配置并启动守护进程
```bash
[root@remote ~]# vim /etc/rsyncd.conf
uid = rsync # 虚拟用户egon对应的就是该用户的权限,限制的是客户端的权限
gid = rsync # 虚拟用户egon对应的就是该组的权限,限制的是客户端的权限,
port = 873
fake super = yes
use chroot = no
max connections = 200
timeout = 600
ignore errors
read only = false
list = false
auth users = egon
secrets file = /etc/rsync.passwd
log file = /var/log/rsyncd.log
#####################################
[xxx]
comment = "备份文件的目录"
path = /egon_bak
```
rsync默认配置文件各配置项详解如下,注意不要将注释卸卸载配置项后面
```bash
[root@remote ~]# vim /etc/rsyncd.conf
#客户端以虚拟用户egon登录成功后,会转换成uid指定的身份,然后以该身份来完成对目标目录的写操作
uid = rsync
#客户端以虚拟用户egon登录成功后,转换成的组身份
gid = rsync
#端口
port = 873
#设置为yes,则代表uid可以不为root
#注意,如果想让rsync -a选项能把本地文件的属主和属组也同步到远端
#则必须让远端的守护进程以root用户启动,即设置uid=root、gid=root,并且将fake super改为no
#在rsync -a选项下,本地文件的uid和gid会同步给服务端,但服务端的uid和gid对应的用户和组名有可能与本地不一致,这完全正常
fake super = yes
#安全机制,rsync daemon在传输前是否切换到指定的path目录下,并将其监禁在内
use chroot = no
#最大连接数,0表示没有限制
max connections = 200
#超时时间,确保rsync服务器不会永远等待一个崩溃的客户端,0表示永远等待
timeout = 600
#忽略错误
ignore errors
#关闭只读
read only = false
#查看模块列表,改为true后,在local端可以用命令rsync rsync://192.168.12.39查看远端可用的模块数
list = false
#指定虚拟用户,传输时使用该用户就会对应到真实系统用户rsync的权限,把此处注释掉,可以在模块里设置
#auth users = egon
#指定虚拟用户的密码文件
#secrets file = /etc/rsync.passwd
#日志文件
log file = /var/log/rsyncd.log
# 指定哪些文件不用进行压缩传输
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
###########下面指定模块,并设定模块配置参数,可以创建多个模块###########
# 模块名为xxx,对应的实际目录为/egon_bak
[xxx]
#备注
comment = "备份文件的目录"
#真实文件目录
path = /egon_bak
# 忽略某些IO错误信息
ignore errors
# 指定该模块是否可读写,即能否上传文件,false表示可读写,true表示可读不可写。所有模块默认不可上传
read only = false
# 指定该模式是否支持下载,设置为true表示客户端不能下载。所有模块默认可下载
write only = false
# 客户端请求显示模块列表时,该模块是否显示出来,设置为false则该模块为隐藏模块。默认true
list = false
# 指定允许连接到该模块的机器,多个ip用空格隔开或者设置区间
hosts allow = 10.0.0.0/24
# 指定不允许连接到该模块的机器
hosts deny = 0.0.0.0/32
# 若模块里指定虚拟用户,则把全局的注释掉即可
auth users = rsync_backup
secrets file = /etc/rsyncd.passwd
# 保存auth users用户列表的用户名和密码,每行包含一个username:passwd。
# 由于"strict modes"默认为true,所以此文件要求非rsync daemon用户不可读写。只有启用了auth users该选项才有效。
[yyy] # 以下定义的是第二个模块,未设置虚拟账号,则所有账号都可以操作该模块
path=/bak/
read only = false
ignore errors
```
创建启动守护进程时用到的用户与组
```bash
[root@remote ~]# useradd rsync -s /sbin/nologin -M
```
配置虚拟用户egon的密码文件
```bash
[root@remote ~]# echo "egon:123" > /etc/rsync.passwd # 虚拟用户egon的密码为123,注意这是在服务端的密码文件,里面必须是"用户名:密码"的格式,而在客户端则不一样
[root@remote ~]# chmod 600 !$
```
为模块xxx创建真实的目录
```bash
[root@remote ~]# mkdir /egon_bak
[root@remote ~]# chown -R rsync.rsync /egon_bak/
```
启动守护进程
```bash
# 1、rsync daemon的启动方式很简单。
[root@remote ~]# rsync --daemon # 启动 rsync 服务,以独立监听服务的方式(守护进程)运行
# 注意注意注意:
我们是以root用户启动的rsync进程,所以rsync的进程身份就是root,一定与配置文件中的uid指定的身份区分开
说白了我们以什么用户启动服务端的rsync进程,控制的是服务端软件的权限
而配置文件中的uid控制的则是客户端的权限、对目录/egon_bak的权限
[root@remote ~]# netstat -anpt | grep rsync
tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN 55535/rsync
tcp6 0 0 :::873 :::* LISTEN 55535/rsync
# 2、如果是CentOS 7,则自带启动脚本。
[root@remote ~]# systemctl start rsyncd
# 可以查看启动脚本的内容:cat /usr/lib/systemd/system/rsyncd.service
# 可以看到较本周启动方法也仅仅只是多了一个"--no-detach",该选项表示rsync不将自己从终端上剥离。
```
**!!!强调!!!**
```bash
1、当前登录用户是谁,进程的权限就是谁
例如:
当前登系统的用户为root,我们在root的交互式环境下启动的进程,该进程身份就是root,该进程拥有root级权限
2、配置文件中的uid、gid控制的是远程连接过来的客户端的身份
```
IV:测试
```bash
# 1、在本地拉取
准备:远程主机创建文件
[root@remote ~]# echo "111" > /egon_bak/1.txt
拉取
rsync -az egon@192.168.12.39::xxx /test # 不指定虚拟用户名egon,则默认使用当前用户名
Password: 123 # 输入虚拟用户egon的密码123
# 2、在本地推送
准备:本机机创建文件
echo "222" > /test/2.txt
推送
rsync -az --delete /test/ egon@192.168.12.39::xxx
# 3、若本地不想手动输密码,有两种方式解决
(1) 写入文件
echo 123 > /etc/egon.password # 客户端的密码文件只能写入密码
chmod 600 /etc/egon.password # 必须配置好权限
rsync -az egon@192.168.12.39::xxx /test --password-file=/etc/egon.password
(2) 配置变量
[root@local ~]# export RSYNC_PASSWORD=123 # 变量名是固定的
[root@local ~]# rsync -az egon@192.168.12.39::xxx /test
```
V:限速传输
有些机房会限制机器的流量,在使用scp和rsync的时候都要注意,为了防止出现断流现象,我们必须对自己的数据传输进行一定的限流措施,慢一点总比被掐了的好。
**rsync**限制速度很简单,添加个参数即可bwlimit,后面的值是多少KBytes/s
```bash
# --bwlimit=100
生成一个500M的文件
[root@local ~]# dd if=/dev/zero of=/tmp/egon.txt bs=1M count=500
指定速率传输,-P显示同步的过程及传输时的进度等信息
[root@local ~]# rsync -avzP --bwlimit=10 /tmp/egon.txt egon@192.168.12.39::xxx
# 注意
blocks of data are sent, then if rsync determines the transfer was too fast, it will wait before sending the next data block. The result is an average transfer rate equaling the specified limit.
数据块发送后,如果rsync确定传输速度过快,它将在发送下一个数据块之前等待。结果是平均传输速率等于指定的限制。
所以rsync是是根据传输平均值来调节生成的吞吐量,你看到当前的传输效率比你指定的大也是很正常的。
```
##### 4.2.2.3 两种远程模式的认证方式总结
- 1、基于ssh认证
```bash
I:使用的是远程主机的系统账号与密码
II:通过ssh隧道进行传输
需要远程主机开启sshd服务
只需要双方安装rsync,不需要双方启动rsync,
类似于scp工具,同步操作不局限于rsync中定义的同步文件夹,
```
- 2、基于守护进程认证,即rsync-daemon
```bash
I:使用的是远程主机的虚拟账号,在rsync-daemon认证下,rsync可以把密码写入到一个文件中。
II:在rsync-daemon认证方式下
只需要双方安装rsync,并且远程主机需要开启rsync进程,默认监听tcp的873端口
同步操作只能同步到远程主机指定的目录下
```