jQuery火箭图标返回顶部代码

rsync

目录

一 储备知识 二 rsync介绍与完整备份方案 三 安装 四 rsync的传输方式与工作模式 4.1 两种传输方式 4.2 两种工作模式 4.2.1 本地模式 4.2.2 远程模式 4.2.2.1 远程模式之SSH认证 4.2.2.2 远程模式之守护进程认证 4.2.2.3 两种远程模式的认证方式总结 五 增量备份 六 rsync的优缺点 七 Rsync结合inotify实现数据实时同步 7.1 rsync+inotify介绍 7.2 安装inotify-tools 7.3 inotifywait命令与事件 7.3.1 inotifywait命令 7.3.2 事件分析 7.3.3 rsync+inotify脚本 八 sersync 8.1 sersync介绍 8.2 sersync实战 九 常见问题

一 储备知识

1、什么是备份

备份就是把重要的数据复制一份到其他位置保留起来

2、为何要备份

回顾:运维三大职责
    1、应用程序7*24*365不间断运行=》围绕三层、做好监控
    2、备份-》为了防止数据丢失时,可以通过备份恢复回来
    3、优化性能:提升用户访问速度

3、如何备份之三种备份方案/思想

# 1、全量备份/完全备份(Full Backup)
每次备份的结果都是一次完整的拷贝

# 2、差异备份(Differential Backup)
每次备份时,都是基于第一次完全备份的内容,只备份有差异的数据(新增的、修改的、删除的),例如

第一次备份:完全备份
第二次备份:以当前时间节点的数据为基础,备份与第一次备份内容的差异
第三次备份:以当前时间节点的数据为基础,备份与第一次备份内容的差异
第四次备份:以当前时间节点的数据为基础,备份与第一次备份内容的差异
第五次备份:以当前时间节点的数据为基础,备份与第一次备份内容的差异
。。。

# 3、增量备份(Incremental Backup )
每次备份时,都是基于上一次备份的内容(注意是上一次,而不是第一次),只备份有差异的数据(新增的、修改的、删除的),所以增量备份的结果是一条链,例如

第一次备份:完全备份
第二次备份:以当前时间节点的数据为基础,备份与第一次备份内容的差异
第三次备份:以当前时间节点的数据为基础,备份与第二次备份内容的差异
第四次备份:以当前时间节点的数据为基础,备份与第三次备份内容的差异
第五次备份:以当前时间节点的数据为基础,备份与第四次备份内容的差异
。。。

img

针对上述三种备份方案,如何恢复数据呢

# 1、全量备份的数据恢复

只需找出指定时间点的那一个备份文件即可,即只需要找到一个文件即可

# 2、差异备份的数据恢复
需要先恢复第一次备份的结果,然后再恢复最近一次差异备份的结果,即需要找到两个文件


# 3、增量备份的数据恢复
需要先恢复第一次备份的结果,然后再依次恢复每次增量备份,直到恢复到当前位置,即需要找到一条备份链

综上,对比三种备份方案

  • 1、占用空间:全量 > 差异 > 增量
  • 2、恢复数据过程的复杂程度:增量 > 差异 > 全量

4、备份的位置

本地备份

异地备份(推荐)

5、常用备份工具

1、cp命令:可以,但因其只能在本地拷贝,所以不会用它来备份,而且cp会产生大量文件占用大量inode,还不如用tar
2、scp远程传输
3、rsync远程传输

二 rsync介绍与完整备份方案

(1)rsync是什么

rsync 全称remote synchronize,即"远程同步",是Liunx/Unix下的一个远程数据同步工具。它可通过LAN/WAN快速同步多台主机间的文件和目录,并适当利用rsync算法(差分编码)以减少数据的传输。

(2)rsync是用来干什么的?

我们用rsync 是为了备份的,这种说法不够准确,容易让人误解,其实rsync的工作只是用来完成远程同步的、只是为异地备份数据做好了一个铺垫,且听我细细道来。

首先:本地备份不可靠的,为什么呢?

如果一份重要数据在本地的某个文件夹里存放着,并且该文件夹内的数据每天都可能会发生变化,为了防止某一天数据突然丢失的情况下我们可以找回数据,我们需要结合计划任务把每天的数据都备份一下然后存在本机,此时,备份是有了,但这就万无一失了吗?错!如果本机挂掉了,你备份的数据都不可用,所以备份的数据一定需要传送到远端,那么你的思路可能是这样的

结合计划任务

1、每天备份一下数据,此时备份的数据是在本地存放着

2、然后将备份的数据发送到远端

3、隔一段时间就删除七天前的本地备份数据,只留下七天内的,节省本地空间

上述思路既浪费空间,传输效率又低,而且如果本机的计划任务尚未触发本机就挂了,异地将获取不到备份数据

我们可以这么做

# 一 制异地镜像
计划任务+rsync将本地数据定期同步到异地->无法做到实时同步
rsync+inotify或sersync将本地数据实时同步到异地->可以做到实时同步,异地就是本地的一个镜像点

# 二 结合计划任务对异地镜像点的目录做增量备份

体会下上述方案

1、本机无需再做备份,我们只需要对远程的镜像站点制作备份即可,因为远程的镜像点与本机完全一致/同步
这样就节省了本机的空间,并且减少了本机的工作量

2、如果本机突然挂掉,不必担心丢失最近的数据,因为远程的镜像点与本机的数据是同步的,本机挂了,远程的镜像点仍然可以保留下最近的数据,亦可对其进行一次备份。

3、如果本机挂掉了,不必担心数据无法恢复,因为备份的数据也都在远程存放着呢。

(3)rsync的原理与特点

rsync的远程传数据可以简单总结为三步

1、先验证用户身份
2、检测出到底需要传哪些文件,默认quick check算法(依据源路径与目标路径下对应文件的大小或修改时间是否有变动),检测出需要传输的文件后,并非是将文件全部传到远端,而是只传文件改动的部分,俗称增量,然后传到远端后,远端再依据之前的内容与传过来的新内容按照算法拼成一个新文件,所以说rsync并不耗费IO,但是耗cpu
3、传输

rsync的特点

  • 1、IO效率高,但耗费cpu资源 与其他远程文件传输工具(如 FTP 或 scp)不同的是,rsync 的最大特点是会检查发送方和接收方对应的、已有的文件,然后仅传输有变动的部分。 因此,在第一次rsync远程同步时,远端无任何内容,所以同步的是全量,以后每次都只是传内容有改变的部分,而不是全部传,这可以极大地节省带宽与传输时间,因此rysnc的IO效率比较高,这在做镜像方面是很不错的。 但是传到远端后,远端再依据之前的内容与传过来的新内容按照算法拼成一个新文件,这是非常耗费cpu计算资源的 综上rsync不适用于的场景如下 # 1、源路径下的内容都不能算是经常改动的,而是频繁改动的场景,rsync不适合,比如数据库文件 如果源路径频繁改动,rsync将时刻处于高频计算中,因为rsync的底层算法要计算出改动的位置然后把文件分段后再进行重新拼接,io没啥问题,cpu都得累死 # 2、不适合同步大文件 因为一个10T的文件但凡修改一个字符,远程同步时只会传一个字符,这并不影响io,但是该字符到达远端后,远端主机的rsync却需要把之前文件的内容与该字符拼成一个新文件,如果文件过大,背后的算法是非常消耗cpu资源的,而且跟重写了一个文件也没多大区别
  • 2、rsync可以实现类似scp的本地路径与远程路径之间的拷贝(rsync不支持远程到远程的拷贝,即源路径与目标路径都是远程路径,但scp支持这一点) scp我们经常都是远端到本地,本地到远端, 远端到远端其实scp也是可以的,只不过看不到进度 scp -pr3 root@192.168.12.17:/root/1.txt root@192.168.12.39:/aaa -p保留权限 -r递归 -3就是远端到远端了 # 依次输入源主机的密码+回车,然后再输入目标主机的密码+回车即可
  • 2、rsync虽然是远程同步,但也支持两个本地目录之间同步文件,因此它也可以当作文件复制工具,所以说rsync相当于是集成了cp和scp的功能,但是他们的底层机制不一样
  • 4、rsync的远程同步是跨平台的
linux --> windows   
windows --> linux   
linux --> mac  
mac --> linux  
mac --> windows

三 安装

注意,传输的双方都必须安装 rsync

yum install rsync -y

四 rsync的传输方式与工作模式

4.1 两种传输方式

1.pull 拉-> 下载
客户端将服务器上的数据下载到本地服务器
问题:如果客户端过多,会对服务端造成压力过大

2.push 推-> 上传
客户端将本地数据上传到服务器
问题:如果客户端过多,上传速度会受到带宽影响,很慢

4.2 两种工作模式

4.2.1 本地模式

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: 拷贝文件

[root@local ~]# rsync /etc/passwd /test

示例2:拷贝文件夹,-r,验证源路径带/后缀与不带后缀的两种情况

[root@local ~]# rsync -r /etc/cron.d /test  # 把文件夹cron.d拷贝到/test下
[root@local ~]# rsync -r /etc/cron.d/ /test  # 把文件夹cron.d下的内容拷贝到/test下

实例3:拷贝文件夹,-R,使用相对目录

[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选项,对目标目录下已经存在的文件做一个备份

[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"指定备份后缀,例如

[root@remote ~]# rsync -r --backup --suffix=".bak" /egon111/ /egon222/

可以使用"--backup-dir"指定备份文件保存路径,但要求保存路径必须存在,指定备份路径后,默认将不会加备份后缀,除非使用"--suffix"显式指定后缀,如"--suffix=~"。

[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... ---> 不变

其他选项

# 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认证

# 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:拉取

[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可以省略。

$ rsync -av -e ssh source/ user@remote_host:/destination

但是,如果 ssh 命令有附加的参数,则必须使用-e参数指定所要执行的 SSH 命令。

$ rsync -av -e 'ssh -p 8888' source/ user@remote_host:/destination

上面命令中,-e参数指定 SSH 使用2234端口。

4.2.2.2 远程模式之守护进程认证

\1) 守护进程模式之rsync协议

守护进程模式其实也是一种远程模式,只不过采用的是rsync协议传输,
若想采用rsync协议传输,则需要远程主机也安装rsync,并启动rsync守护进程,此时不需要依赖远程主机的sshd服务

2)为什么使用守护进程模式

1.基于ssh的认证,传输时会使用系统用户和密码,不安全,而守护进程模式使用的是虚拟用户和虚拟密码
2.当使用普通用户传输文件时会出现权限不足的情况,而守护进程模式可以解决这个问题

3)如何使用rsync协议传输

在传输时,如果未指定协议,则默认用ssh协议,指定使用rsync协议的方式有两种

# 方式一: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 角色
本地与远程均执行下述两条命令
setenforce 0
iptables -F

II:安装rsync(本地和远程主机都要装)

[root@remote ~]# yum install rsync -y

III:在远程主机配置并启动守护进程

[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默认配置文件各配置项详解如下,注意不要将注释卸卸载配置项后面

[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

创建启动守护进程时用到的用户与组

[root@remote ~]# useradd rsync -s /sbin/nologin -M

配置虚拟用户egon的密码文件

[root@remote ~]# echo "egon:123" > /etc/rsync.passwd  # 虚拟用户egon的密码为123,注意这是在服务端的密码文件,里面必须是"用户名:密码"的格式,而在客户端则不一样
[root@remote ~]# chmod 600 !$

为模块xxx创建真实的目录

[root@remote ~]# mkdir /egon_bak
[root@remote ~]# chown -R rsync.rsync /egon_bak/

启动守护进程

# 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不将自己从终端上剥离。

!!!强调!!!

1、当前登录用户是谁,进程的权限就是谁
例如:
当前登系统的用户为root,我们在root的交互式环境下启动的进程,该进程身份就是root,该进程拥有root级权限
2、配置文件中的uid、gid控制的是远程连接过来的客户端的身份

IV:测试

# 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

# --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认证
I:使用的是远程主机的系统账号与密码
II:通过ssh隧道进行传输
    需要远程主机开启sshd服务
    只需要双方安装rsync,不需要双方启动rsync,
    类似于scp工具,同步操作不局限于rsync中定义的同步文件夹,
  • 2、基于守护进程认证,即rsync-daemon
I:使用的是远程主机的虚拟账号,在rsync-daemon认证下,rsync可以把密码写入到一个文件中。
II:在rsync-daemon认证方式下
    只需要双方安装rsync,并且远程主机需要开启rsync进程,默认监听tcp的873端口
    同步操作只能同步到远程主机指定的目录下

五 增量备份

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中的文件。这个命令的第一次备份时是全量备份,后面就都是增量备份了。

[root@local ~]# mkdir /data
[root@local ~]# echo 111 > /data/1.txt
[root@local ~]# echo 222 > /data/2.txt
[root@local ~]# 
[root@local ~]# mkdir /bak
[root@local ~]# 
[root@local ~]# 
[root@local ~]# # 第一次,全量
[root@local ~]# rsync -a --delete /data/ /bak/111/
[root@local ~]# 
[root@local ~]# # 比较上一次备份与当前/data,将增量备份到新目录中
[root@local ~]# echo 333 > /data/3.txt  
[root@local ~]# rsync -a --delete --link-dest /bak/111/ /data/ /bak/222  # 
[root@local ~]# echo 666 >> /data/1.txt 
[root@local ~]# rsync -a --delete --link-dest /bak/222 /data/ /bak/333
[root@local ~]# rm -rf /data/2.txt 
[root@local ~]# rsync -a --delete --link-dest /bak/333 /data/ /bak/444
[root@local ~]# 

与传统的增量备份略有不同的是,rsync的每次增量都会保留源目录中的全部文件,但是若文件较之上一次没有变化,则新备份中的文件只是创建了一个指向上一次对应文件的硬链接,这就保证了在不浪费空间的前提下保证了rsync的增量备份在恢复数据时,只需要找到一份备份既可以恢复到指定的状态,这就使得其数据恢复过程的简洁性与完全备份一样了,但它还比全量备份的数据量要小很多。

下面是一个脚本示例,备份/opt目录。

#!/bin/bash

# A script to perform incremental backups using rsync

set -o errexit  # 它使得脚本只要发生错误,就终止执行,而不是一声不响地往下执行

set -o nounset  # 在shell中,遇到变量不存在,并不会报错,而是输出空,然后继续执行后续代码
                # 开启nounset选项后,脚本若碰到变量为定义则报错并终止运行
                
                
set -o pipefail  # 上面的选项errexit针对管道命令是无效的,比如xxx | echo "egon",并不存在
                 # xxx命令,但是该管道命令整体是执行成功的,加上pipefail选项后则可以防止这件事

readonly SOURCE_DIR="/opt"  # 备份的源目录
readonly TARGET_START_DIR="/egon/backups"  # 目标目录的起始目录
readonly TARGET_DIR="${TARGET_START_DIR}/$(date '+%Y-%m-%d_%H:%M:%S')"  # 目标目录
readonly LATEST_LINK="${TARGET_START_DIR}/latest"  # 基准目录

mkdir -p "${TARGET_START_DIR}"  # 先把目标目录的起始目录创建好

rsync -av --delete \
  "${SOURCE_DIR}/" \
  --link-dest "${LATEST_LINK}" \
  --exclude=".cache" \
  "${TARGET_DIR}"

# 删除基准目录LATEST_LINK,然将最新一次备份ok的目标目录链接到LATEST_LINK作为下一次的基准目录
rm -rf "${LATEST_LINK}"
ln -s "${TARGET_DIR}" "${LATEST_LINK}"

解释

1、首次执行该脚本
--link-dest指定的基准目录并不存在,但rsync命令仍会执行成功,不会报错
所以首次执行是只参照备份的源目录SOURCE_DIR进行的备份,即全量备份,目录目录下都是全新的文件

首次执行完毕后,会将最新一次备份的成果TARGET_DIR链接成基准目录,这样下一次执行rsync就有了基准目录

2、第二次执行该脚本
此时执行脚本时,用户可能已经改动了源目录里的内容(新增了文件或者改动了某个文件)
所以此刻的源目录跟当初的源目录依然不同了,如果找到这个不同呢?这就用到了上一次备份留给我们的基准目录,即
SOURCE_DIR + 上一次备份留给我们的基准目录LATEST_LINK ===》得出增量

然后将增量备份到一个新的目标目录,目标目录以当前时间命名
注意注意注意,此时的目标目录拥有与当前源目录一模一样的文件,但实际上,这些文件中,只有那些变动过的文件是刚刚新建/备份到该目录中的,其他没有变动的文件都是直接指向基准目录文件的硬链接而不是重新拷贝了一份。
所以,因为采用的是硬链接,基于rsync的增量备份在恢复数据时,只需要去/egon/backups找对应时间的目录即可,那里面每个目录里存放的就是对应时间节点的所有数据

删除上一次的基准目录,然后将当前刚刚备份好的、最新的目标目录链接成新的基准目录,为下一次增量做好准备

3、第三次执行该脚本
同上,都是增量

总结

# 1、首次执行为全量
# 2、后续执行为增量,后续的每次备份产生的以时间命名的目标目录TARGET_DIR都代表着当前的最新状态,但旧的、未曾改动的文件都是指向上一次备份的TARGET_DIR
# 3、数据恢复时,只需要找到对应时间的目标目录即可,那里面每个目录里存放的就是对应时间节点的所有数据,无需按照传统的增量恢复->先恢复全量,再依次恢复每次增量一直到当前想要的时间节点

六 rsync的优缺点

# 1、优点:

安全性高

备份迅速,使用同步算法,只比较变化

支持增量备份

保存源目录整个目录树和文件系统

保持源文件的权限、时间、软硬连接等

无需特使权限即可安装

优化流程和比较高的文件传输效率。

多样方式来传输文件。

支持匿名运行,方便网站镜像。

与scp相比,rsync传输速度远在scp之上。(局域网测试,rsync是scp的20倍)

# 2、不足:

同步数据,需要扫描所有文件进行对比,才进行差量传输。如果文件数量达到百万甚至千万级,扫描文件对比文件将非常耗时,降低了rsync效率。

rsync不能实时地区监测、同步数据。虽然可以通过守护进程方式触发同步,但两次动作间有时间差,导致数据不一致,无法应对出现故障时完全恢复数据。

解决: rsync+inotify来弥补不足。

七 Rsync结合inotify实现数据实时同步

7.1 rsync+inotify介绍

rsync+crond:只能实现数据的间隔同步(最小也是分钟级别的同步),无法实现实时同步,如果要做异地镜像点,肯定是需要实时同步的。

在Linux kernel 2.6.13后提供了inotify文件系统监控机制。通过rsync+inotify组合可以实现实时同步,制作异地镜像站点,以便为异地备份做好准备工作

7.2 安装inotify-tools

inotify由inotify-tools包提供。在安装inotify-tools之前,请确保内核版本高于2.6.13,且在/proc/sys/fs/inotify目录下有以下三项,这表示系统支持inotify监控,关于这3项的意义,下文会简单解释。

[root@local ~]# ll /proc/sys/fs/inotify/
total 0
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_queued_events
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_instances
-rw-r--r-- 1 root root 0 Feb 11 19:57 max_user_watches

epel源上提供了inotify-tools工具,或者下载源码包格式进行编译。

inotify-tools源码包地址:https://cloud.github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz

以下为编译安装过程:

tar xf inotify-tools-3.14.tar.gz
./configure --prefix=/usr/local/inotify-tools-3.14
make && make install
ln -s /usr/local/inotify-tools-3.14 /usr/local/inotify

inotify-tools工具只提供了两个命令。

[root@local ~]# rpm -ql inotify-tools | grep bin/
/usr/bin/inotifywait
/usr/bin/inotifywatch

其中inotifywait命令用于等待文件发生变化,所以可以可以实现监控(watch)的功能,该命令是inotify的核心命令。inotifywatch用于收集文件系统的统计数据,例如发生了多少次inotify事件,某文件被访问了多少次等等,一般用不上。

以下是inotify相关的内核参数。

(1)./proc/sys/fs/inotify/max_queued_events:调用inotify_init时分配到inotify instance中可排队的event数的最大值,超出值时的事件被丢弃,但会触发队列溢出Q_OVERFLOW事件。 (2)./proc/sys/fs/inotify/max_user_instances:每一个real user可创建的inotify instances数量的上限。 (3)./proc/sys/fs/inotify/max_user_watches:每个inotify实例相关联的watches的上限,即每个inotify实例可监控的最大目录、文件数量。如果监控的文件数目巨大,需要根据情况适当增加此值。

如:

[root@xuexi ~]# echo 30000000 > /proc/sys/fs/inotify/max_user_watches

7.3 inotifywait命令与事件

7.3.1 inotifywait命令

选项 说明

–format 参数说明:

参数 说明

-e指定的监控事件

create:在被监控的目录中创建了文件或目录
delete:删除了被监控目录中的某文件或目录
modify:修改,文件内容被修改
access:文件被访问
attrib:元数据被修改。包括权限、时间戳、扩展属性等等

close_write:打开的文件被关闭,是为了写文件而打开文件、随后被关闭的事件,比如用vim编辑文件或者echo 1111 >> egon.txt 
close_nowrite:read only模式下文件被关闭,即只能是为了读取而打开文件,读取结束后关闭文件的事件
close:是close_write和close_nowrite的结合,无论是何种方式打开文件,只要关闭都属于该事件
open:文件被打开
moved_to:向监控目录下移入了文件或目录,也可以是监控目录内部的移动
moved_from:将监控目录下文件或目录移动到其他地方,也可以是在监控目录内部的移动
move:是moved_to和moved_from的结合
moved_self:被监控的文件或目录发生了移动,移动结束后将不再监控此文件或目录
delete_self:被监控的文件或目录被删除,删除之后不再监控此文件或目录
umount:挂载在被监控目录上的文件系统被umount,umount后不再监控此目录
isdir :监控目录相关操作

7.3.2 事件分析

监控目录

[root@egon ~]# mkdir /egon_bak
[root@egon ~]# inotifywait -m /egon_bak/ #在前台监控目录/egon_bak,未指定监控的事件,默认监控所有
Setting up watches.
Watches established.


打开另外一个终端,对被监控目录/egon_bak进行一些操作,来查看触发的事件

验证文件的增删改查,vim编辑文件,cp拷贝,mv移动文件等操作触发的事件
验证目录的增删改查,cp拷贝文件到目录下,mv移入移出等操作触发的事件

大致总结如下

# 文件的增删改
监控目录下新增了某个文件->触发的事件:
CREATE
MODIFY
CLOSE_WRITE,CLOSE

监控目录下的某个文件被删除->触发的事件
DELETE

监控目录下的某个文件内容被修改->触发的事件
MODIFY
CLOSE_WRITE,CLOSE


监控目录下的某个文件属性被修改->触发的事件
ATTRIB

监控目录下的某个文件被mv到别的目录中->出发的事件
MOVED_FROM

某个文件被mv到了监控目录或其子目录下->出发的事件
MOVED_TO

# 目录的增删改同上
CREATEXISDIR
DELETEXISDIR
ATTRIBXISDIR
MOVED_FROMXISDIR
MOVED_TOXISDIR

从上面的测试结果中可以发现,很多动作都涉及了close事件,且大多数情况都是伴随着close_write事件的。所以,大多数情况下在定义监控事件时,其实并不真的需要监控open、modify、close事件。特别是close,只需监控它的分支事件close_write和close_nowrite即可。由于一般情况下inotify都是为了监控文件的增删改,不会监控它的访问,所以一般只需监控close_write即可。

由于很多时候定义触发事件后的操作都是根据文件来判断的,例如a文件被监控到了变化(不管是什么变化),就立即执行操作A,又由于对文件的一个操作行为往往会触发多个事件,例如cat查看文件就触发了open、access、close_nowrite和close事件,这样很可能会因为多个事件被触发而重复执行操作A。

综合以上考虑,我们应该尽量做到监控对象减少重复,但这一点其实很难实现

inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%w%f:%Xe:%T' -e create,delete,modify,move,attrib,close_write /test

7.3.3 rsync+inotify脚本

该脚本需要运行在本地 ,并且需要远端开启rsyncd

#!/bin/bash
 
watch_dir=/test/               # 本地被监控目录
user="egon"                    # 虚拟用户
export RSYNC_PASSWORD=123      # 虚拟用户密码
module="xxx"                   # 远程模块名
ip=192.168.12.39               # 远程主机ip

# 先整体同步一次
rsync -azc --delete ${watch_dir} ${user}@${ip}::${module}

# 切换到被监控目录下,然后用inotifywait监控./目录,这样后期就可以用-R选项同步新增的子目录
cd $watch_dir  
/usr/bin/inotifywait -mrq --timefmt '%Y-%m-%d %H:%M:%S' --format '%w%f:%Xe:%T' -e create,delete,modify,move,attrib,close_write ./ \
--exclude=".*.swp" | \
while read line
do
    # $line的输出format为:文件路径:事件:时间
    FILE=$(echo $line | awk -F: '{print $1}')  # 获取文件的绝对路径
    EVENT=$(echo $line | awk -F: '{print $2}') # 获取监控的事件

    # 监控到对文件的下述行为后,只把文件同步到远端
    if [[ $EVENT =~ 'CREATE' ]] || [[ $EVENT =~ 'MODIFY' ]] || [[ $EVENT =~ 'CLOSE_WRITE' ]] || [[ $EVENT =~ 'MOVED_TO' ]] || [[ $EVENT =~ 'ATTRIB' ]];then
        rsync -azcR ${FILE} ${user}@${ip}::${module}
    fi
    
    # 监控到涉及到目录的改动,将目录同步到远端,例如用dirname ${FILE}获取目录
    if [[ $EVENT =~ 'DELETE' ]] || [[ $EVENT =~ 'MOVED_FROM' ]];then
        rsync -azcR --delete $(dirname ${FILE}) ${user}@${ip}::${module} &>/dev/null
    fi
done &
# 末尾的&符号,代表在子shell中提交命令,这样进程的ppid就变为1,当前窗口关闭,该进程依然存活

远程(配置好rsync守护进程,模块为xxx,虚拟用户名egon,密码123),执行下述命令检测同步情况

while true;do ls /egon_bak;sleep 0.5;clear;done

八 sersync

8.1 sersync介绍

rsync+inotify的缺点

  • 1、inotify最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件(例如,当监控目录中有5个文件时,删除目录时会产生6个监控事件),从而导致重复调用rsync命令。而且vim文件时,inotify会监控到产生临时文件.swp和.swx等的事件,但这些事件相对于rsync来说是不应该被监控的。
  • 2、inotifywait工具的存在缺陷,当向监控目录下拷贝复杂层次目录(多层次目录中包含文件),或者向其中拷贝大量文件时,inotifywait经常会随机性地遗漏某些文件
  • 3、并发如果大于200个文件(10-100K),同步会有延迟
  • 4、监控到事件后,调用rsync同步是单线程的(加&才可以并发)

由于上述缺陷的存在,使得通过脚本实现的inotify+rsync几乎很难达到完美,于是sersync应运而生!

sersync是金山的周洋基于rsync+inotify-tools开发的工具,它克服了inotify的缺陷,可以过滤重复事件减轻负担,并且自带crontab功能、多线程调用rsync、失败重传等功能,详解如下

# 1、sersync的优点:
1、sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤,所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。

2、sersync配置很简单,其中bin目录下已经有静态编译好的2进制文件,配合bin目录下的xml配置文件直接使用即可。

3、sersync使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态。

4、sersync有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步。

5、sersync自带crontab功能,只需在xml配置文件中开启,即可按要求隔一段时间整体同步一次。无需再额外配置crontab功能。

6、sersync可以二次开发。

# 2、sersync的缺点:
sersync有重传机制(内置的定时任务),但是只重传一次,如果重传失败就会清空重传队列,即清空/tmp/rsync_fail_log.sh文件。这样就会造成sersync服务恢复正常后(即可以同步文件),数据同步的两个服务器数据不一致的现象。因为,/tmp/rsync_fail_log.sh文件为空,而sersync只对发生变化的文件做实时同步(ps:sersync默认每隔十个小时做一次完整的数据同步)。

注意

(1)当同步的目录数据量不大时,建议使用rsync+inotify

(2)当同步的目录数据量很大时(几百G甚至1T以上)文件很多时,建议使用rsync+sersync

8.2 sersync实战

1)环境准备

主机 IP 安装服务

2)服务端安装与配置好rsync守护进程(略)

3)客户端安装rsync和inotify

yum install -y rsync inotify-tools

4)客户端安装sersync

# 1、下载
wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz

# 2、解压即可用
tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz

# 3、把软件移动到/usr/local/sersync下
mv GNU-Linux-x86 /usr/local/sersync

# 4、制作环境变量
echo "export PATH=$PATH:/usr/local/sersync" >> /etc/profile
source /etc/profile

修改配置

[root@local ~]# vim /usr/local/sersync/confxml.xml 
<!--?xml version="1.0" encoding="ISO-8859-1"?-->

    # 监听的主机和端口
    <host hostip="localhost" port="8008"></host>
    
    # 是否开启调试模式,下面所有出现false和true的地方都分别表示关闭和开启的开关
    <debug start="false">
    
    # 监控的是否是xfs文件系统,默认为false
    <filesystem xfs="true">
    
    # 是否启用监控的筛选功能,筛选的文件将不被监控
    <filter start="false">
    <exclude expression="(.*)\.svn"></exclude>
    <exclude expression="(.*)\.gz"></exclude>
    <exclude expression="^info/*"></exclude>
    <exclude expression="^static/*"></exclude>
    </filter>
    
    # 监控的事件,默认监控的是delete/createFolder/closeWrite/moved_from/moved_to
    <inotify>
    <delete start="true">
    <createfolder start="true">
    <createfile start="true">
    <closewrite start="true">
    <movefrom start="true">
    <moveto start="true">
    <attrib start="true">
    <modify start="true">
    </modify></attrib></moveto></movefrom></closewrite></createfile></createfolder></delete></inotify>

    <sersync>  # rsync命令的配置段
    <localpath watch="/test">  # 监控的本地目录
        # 默认为rsync协议认证,除非下面开启ssh start
        # 所以此处为远程主机的ip与模块名,远端要开启rsync守护进程
        <remote ip="192.168.12.39" name="xxx"> 
        <!--<remote ip="192.168.8.39" name="tongbu"/>-->
        <!--<remote ip="192.168.8.40" name="tongbu"/>-->
    </remote></localpath>
    <rsync>
        # 指定rsync选项,默认为-artuz
        <commonparams params="-az">
        
        # 开启认证,需要虚拟用户和密码文件,默认是关闭的
        <auth start="true" users="egon" passwordfile="/etc/egon.password">
        # 如果端口不是873则需要更改
        <userdefinedport start="false" port="874"><!-- port=874 -->
        # 超时时间
        <timeout start="false" time="100"><!-- timeout=100 -->
        # 是否使用远程shell模式而非rsync daemon运行rsync命令
        <ssh start="false">
    </ssh></timeout></userdefinedport></auth></commonparams></rsync>
    
    # 错误重传
    <faillog path="/tmp/rsync_fail_log.sh" timetoexecute="60"><!--default every 60mins execute once-->
    
    # 是否开启crontab功能,默认关闭,每隔600分钟进行一次全备
    <crontab start="true" schedule="600"><!--600mins-->
        <crontabfilter start="false">  # crontab定时传输的筛选功能
        <exclude expression="*.php"></exclude>
        <exclude expression="info/*"></exclude>
        </crontabfilter>
    </crontab>
    <plugin start="false" name="command">
    </plugin></faillog></sersync>

    # 以下不需要修改
    <plugin name="command">
    <param prefix="/bin/sh" suffix="" ignoreerror="true">  <!--prefix /opt/tongbu/mmm.sh suffix-->
    <filter start="false">
        <include expression="(.*)\.php">
        <include expression="(.*)\.sh">
    </include></include></filter>
    </plugin>

    <plugin name="socket">
    <localpath watch="/opt/tongbu">
        <deshost ip="192.168.138.20" port="8009">
    </deshost></localpath>
    </plugin>
    <plugin name="refreshCDN">
    <localpath watch="/data0/htdocs/cms.xoyo.com/site/">
        <cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx">
        <sendurl base="http://pic.xoyo.com/cms">
        <regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images">
    </regexurl></sendurl></cdninfo></localpath>
    </plugin>

依据配置文件创建密码文件并授权

echo 123> /etc/egon.password
chmod 600 /etc/egon.password

sersync2命令

[root@local ~]# sersync2 -h
set the system param
execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events
parse the command param
_______________________________________________________
参数-d:启用守护进程模式
参数-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
c参数-n: 指定开启守护线程的数量,默认为10个
参数-o:指定配置文件,默认使用confxml.xml文件
参数-m:单独启用其他模块,使用 -m refreshCDN 开启刷新CDN模块
参数-m:单独启用其他模块,使用 -m socket 开启socket模块
参数-m:单独启用其他模块,使用 -m http 开启http模块
不加-m参数,则默认执行同步程序

由此可见,sersync2命令总是会先设置inotify相关的系统内核参数。

所以,只需执行以下简单的命令即可。

/usr/local/sersync/sersync2 -dro /usr/local/sersync/confxml.xml

如果在本机要监控多个目录,即sersync多实例,只需分别配置不同配置文件,然后使用sersync2指定对应配置文件运行即可。

九 常见问题

问题

protocol version mismatch -- is your shell clean?
(see the rsync man page for an explanation)
rsync error: protocol incompatibility (code 2) at compat.c(178) [sender=3.1.2]

分析与解决方案

# 1、原因是
rsync 在传输数据之前,会先与远端进行一次 ssh 登录认证,而当 .bashrc文件有输出的时候,rsync 客户端解析返回的数据包会出现混乱,于是乎就会出现文中开头提到的报错:客户端和远端的协议版本不兼容/不匹配了。

# 2、需要说明的是:
远端 sshd 进程是通过“bash –c”的方式来执行命令(即"非交互式的非登录shell" )

但在执行命令之前,ssh的那一次登录本身是“非交互式的登录shell”, 非交互式的登录shell (bash –l xxx.sh) 载入的信息列表及顺序如下:

/etc/profile
~/.bash_profile ( ->  ~/.bashrc  ->  /etc/bashrc)
~/.bash_login
~/.profile
$BASH_ENV
所以 ssh 的时候会载入“ ~/.bash_profile”,

让我们再来看一下 .bash_profile 的内容:

cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
  . ~/.bashrc  # .bashrc 默认又会加载 /etc/bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin

export PATH
看到这儿,我想你大概明白了为什么 .bashrc 里有输出流会导致 rsync 传输失败了。

# 3、解决方案
既然都找到原因了,那怎么解决呢?
最简单的方案当然是直接删掉.bashrc文件输出的内容

但有同学会问,我本来就是要让用户登录的时候有登录提示的呀?现在为了 rsync 岂不是得禁掉?

那这里就又引入了另一个知识点:交互式shell和飞交互式shell、登录shell和非登录shell 的区别

什么是交互式的呢?就像我们平时通过命令行做事一样,你敲一个命令,终端解析执行完之后给你一个结果,这样一种交互式的形式。那么,平时我们接触的Shell基本上都是交互式的,如gnome-terminal打开一个Shell以及通过Ctrl+alt+1等切换过去的文本终端。交互式Shell下, "echo $-"返回的字符串中包含i,否则不包含。也可以通过在bash后面加-i参数打开一个交互式的Shell,具体可以看man bash。bash后面加-c参数执行命令打开的是非交互式Shell,可以用以下命令验证:

bash -c 'echo $-'  # 返回hBc
解释完交互式之后,继续解析本小节后半部分中的登录二字。登录Shell其实很好理解,就是我们平时通过用户名/密码才能登录的Shell,最典型的就是用Ctrl+alt+1切换过去的文本终端。如何区分登录Shell和非登录Shell呢,可以通过查看$0的值,登录Shell返回-bash,而非登录Shell返回的是bash。平时gnome-terminal打开的Shell就是非登录Shell。也可以通过在bash后面加--login参数打开一个登录Shell。

回到本小节开头的问题,咱们可以用如下方式去区分一个命令是处于登录shell还是非登录shell:

[[ $- == *i* ]] && echo 'This is interactive shell.'
其中,$-中包含i意思是指当前的Shell是一个交互式(interactive)的Shell。

针对文中开头的问题,咱们加上如上的判断,就可以做到登录的时候有提示,同时 rsync 也不会报错了,可谓一举两得。

好了,今天的内容就到这儿了,其实 shell 作为一门古老的编程语言以及随着 linux 版本的多样化发展、不断的演变,”坑“很多,却也值得让人细细探索~

其他常见错误

1.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::backu
@ERROR: Unknown module 'backu'
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]
#原因:模块名字写错了

2.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backu@172.16.1.41::backup
@ERROR: auth failed on module backup
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]
#原因:
    1)虚拟用户写错了
    2)虚拟用户密码写错了
    3)密码文件权限不对,一定是600

3.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::backup
rsync: failed to connect to 172.16.1.41 (172.16.1.41): No route to host (113)
rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]
#原因:开启了防火墙

4.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::/backup
ERROR: The remote path must start with a module name not a /
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]
#原因:::后面跟的时模块名

5.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::backup/
sending incremental file list
rsync: delete of stat xattr failed for "1.txt" (in backup): Permission denied (13)

sent 47 bytes  received 107 bytes  308.00 bytes/sec
total size is 0  speedup is 0.00
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1179) [sender=3.1.2]
#原因:
    1)服务端真实目录权限不足
    2)selinux没有关闭

6.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::backup/
rsync: failed to connect to 172.16.1.41 (172.16.1.41): Connection refused (111)
rsync error: error in socket IO (code 10) at clientserver.c(125) [sender=3.1.2]
#原因:服务端服务没有启动

7.报错:
[root@web01 ~]# rsync -avz 1.txt rsync_backup@172.16.1.41::backup/
@ERROR: chdir failed
rsync error: error starting client-server protocol (code 5) at main.c(1649) [sender=3.1.2]
#原因:服务端没有模块指定的目录
```</filesystem></debug>
posted @ 2021-11-29 16:22  墨颜丶  阅读(456)  评论(0编辑  收藏  举报