Rsync

一、基础知识

1.1 Rsync简介

  可实现全量及增量、本地或远程的数据同步备份的工具
  官网:https://www.samba.org/ftp/rsync/rsync.html
  相当于cp(本地复制)、scp(远程复制)、rm(删除)命令的合体但比这三个命令更优秀
  既能够备份数据内容,也能够备份属性信息

  同步目录时,若以"/"结尾,则表示同步目录下所有文件,不会连同目录一起同步;若不以"/"结尾,则表示同步目录下所有文件,并连同目录一起同步

1.2 Rsync优缺点:

优点 缺点

支持拷贝特殊文件如链接文件,设备等

大量小文件同步的时候,时间较长,有时候rsync进程可能会停止

可以有排除指定文件或目录同步的功能,相当于打包命令tar的排除功能

同步10G这样的大文时时,可能会中断,未完整同步前,是隐藏文件

可以做到保持元文件或目录的权限、时间、软硬链接、属主、组等所有属性均不变

rsync本身不对数据加密,需配合ssh等实现加密

可实现增量同步,默认只同步发生变化的数据(大小或者最后修改时间发生变化的文件或目录),因此同步数据的效率很高

 

可以使用rcp,rsh,ssh等方式来配合传输文件达到加密传输

 

可以通过socket(守护进程方式)传输文件和数据(服务端和客户端)

 

支持匿名的、认证的(无需系统用户)进程模式传输,可方便安全的进行数据备份及镜像

 

 

1.3 Rsync的工作方式

  单个主机本地之间的数据传输(类似于cp)

  借助rcp,ssh等通道来传输数据(类似于scp)

  以守护进程(socket)的方式来传输数据(服务端和客户端)

 

二、普通用法

2.1 基本参数

注:rsync备份时,如果备份/tmp,表示备份目录名和目录下的内容,如果备份/tmp/,表示只备份目录下的内容

参数 说明
-v 详细模式输出,传输时的进度等信息
-z 传输时进行压缩以提高传输效率。--compress-level=NUM可按级别压缩
-a 归档模式,表示以递归方式传输文件,并保持文件所有属性,等于rtopgDI
--append 指定文件接着上次中断的地方,继续传输
--append-verify --append参数类似,但会对传输完成后的文件进行一次校验。如果校验失败,将重新发送整个文件
-r 对子目录以递归传递,即目录下的所有目录都同样传输,注意是小写r
-t 保持文件时间信息
-o 保持文件属主信息
-p 保持文件权限
-g 保持文件属组信息
-D 保持设备文件信息
-l 保留软链接
-H 保留硬链接
-u 仅进行更新,跳过已经存在目标目录的文件,只复制目标目录没有的且文件时间要晚于备份时间的新文件
-P --progress--partial这两个参数的结合
--partial 允许恢复中断的传输。不使用该参数时,rsync会删除传输到一半被打断的文件;使用该参数后,传输到一半的文件也会同步到目标目录,下次同步时再恢复中断的传输。一般需要与--append--append-verify配合使用
--progress 显示同步的过程及传输的进度等信息
--partial-dir 参数指定将传输到一半的文件保存到一个临时目录,比如--partial-dir=.rsync-partial。一般需要与--append--append-verify配合使用。
-e 使用指定的shell程序替代传输用的rsh管道,如ssh(-e 'ssh -p 22')
--exclude=PATTERN 指定排除不需要传输的文件(和tar参数一样)
--exclude-from=file 指定排除某个目录中的某个文件(和tar参数一样)
--include 指定必须同步的文件,往往与--exclude结合使用
--bwlimit=RATE 每秒最大传输速率,用来限制传输时的带宽(避免占用全部网络带宽),默认单位是 KB/s。如--bwlimit=100,则每秒最大传输100kb的数据
--delete 默认情况下,rsync 只确保源目录的所有内容(明确排除的文件除外)都复制到目标目录。它不会使两个目录保持相同,并且不会删除文件。如果要使得目标目录成为源目录的镜像副本,则必须使用--delete参数,这将删除只存在于目标目录、不存在于源目录的文件。
-m 不同步空目录
--max-size 设置传输的最大文件的大小限制,比如不超过200KB(--max-size='200k'
--min-size 设置传输的最小文件的大小限制,比如不小于10KB(--min-size=10k
-n 如果不确定 rsync 执行后会产生什么结果,可以先用-n--dry-run参数模拟执行的结果
--size-only 只同步大小有变化的文件,不考虑文件修改时间的差异
-A 在同步过程中保留文件的访问控制列表(ACLs),等同于--acls,ACLs提供了比传统Unix权限(ugo/rwx)更细粒度的权限控制,例如可以为多个用户或组设置不同的权限,源和目的文件系统都必须支持ACLs
-X 在同步过程中保留文件的扩展属性(xattrs),等同于--xattrs,扩展属性是文件系统中的一种机制,允许用户将键值对附加到文件上,源和目的文件系统都必须支持扩展属性

 

2.2 普通模式

# 本地模式
rsync [OPTION...] 源路径 目的路径

# 远程模式
# 注:前面的是原路径,后面的是目标路径,推和拉的区别仅仅是远端地址所在的位置,远端用户名可省略,省略代表用本机当前用户去连接
推:rsync [OPTION...] [远端用户@]主机名或IP:源路径 目标路径
拉:rsync [OPTION...] 源路径 [远端用户@]主机名或IP:目标路径

 注意: rsync不管是推还是拉,推送目录的时候带/和不带/

  1.带/ :/etc/ 将etc目录里的所有内容(不包括目录),推过去或者拉过来

  2.不带/:/etc 将etc目录整体(包括目录及目录里的所有内容)推过去或者拉过来

 

2.3 示例

# 备份本机hosts文件到tmp目录
rsync -avz /etc/hosts /tmp

# 推送本机hosts文件到另外一台主机tmp目录
rsync -avz /etc/hosts root@172.16.1.31:/tmp/

# 拉取远端主机hosts文件本机tmp目录
rsync -avz root@172.16.1.31:/etc/hosts /tmp/

# 配合ssh加密传输数据[-e]
rsync -avz -e 'ssh -p 22' /etc/hosts root@172.16.1.31:/tmp/

# 同步时排除某些文件[--exclude]
# --exclude参数使用相对路径,可以排除单个和多个文件

# 也可以用--exclude-from=paichu.txt,排除这个文件中指定的文件 rsync
-avz --exclude=a.txt /backup/ root@172.16.1.41:/tmp/ rsync -avz --exclude-from=paichu.txt /backup/ root@172.16.1.41:/tmp/ # 无差异同步[--delete]
# --delete会把服务器上有而本地没有的数据全部删除,非常危险,慎用 rsync
-avz --delete /backup/ root@172.16.1.41:/tmp/ # 限速[--bwlimit] sync -avz --bwlimit=100 /backup/ root@172.16.1.41:/tmp/

 

三、守护进程模式(C/S)

3.1 基础说明

  搭建服务端启动守护进程(873端口),然后在客户端推或拉数据进行备份

  比普通远程模式好的地方在于,免交互的备份数据,常配合定时任务进行定时备份

  在守护进程中,不考虑加/或者不加/

语法:
拉: rsync [OPTION...] [USER@]HOST::SRC DEST
推: rsync [OPTION...] SRC [USER@]HOST::DEST

 

3.2 服务器端配置

添加rsync服务的用户(linux系统自带rsync服务,若没有可yum下载)

useradd -s /sbin/nologin -M rsync

 

生成 /etc/rsyncd.conf 配置文件并写入内容(注释用的#号必须写在行首)

uid = rsync
gid = rsync
port = 873
use chroot = yes
munge symlinks = yes
fake super = yes
log file = /var/log/rsyncd.log
max connections = 10
timeout = 300

[backup]
comment = test
path = /backup
secrets file = /etc/rsyncd.secrets
read only = no
list = yes
auth users = rsync_backup
hosts allow = 10.0.0.0/8

配置文件详解

# 注释用的#号必须写在行首
# 全局参数:配置在文件开头,不在任何 [module] 部分内。这些参数影响整个守护进程或其默认行为。
uid = root                      # 守护进程会以该用户身份执行文件操作。非常重要,影响文件访问权限。
gid = root                      # 守护进程会以该组身份执行文件操作。非常重要,影响文件访问权限。
port = 873                      # 服务默认监听端口
address = ip_address            # 指定 rsync 守护进程绑定的特定 IP 地址,默认监听所有可用网络接口 (0.0.0.0 或 :: for IPv6)
fake super = yes                # 默认no,是否允许非root身份的rsync守护进程(如以`rsync`用户运行)也能保留文件的完整权限信息,包括属主、属组、特殊权限位以及扩展属性,将这些信息以特殊方式存储在文件的扩展属性(xattrs)中。文件系统必须支持扩展属性(xattr),例如ext4、xfs、btrfs等。
use chroot = yes                # 默认yes,是否在传输文件前将守护进程的工作目录切换到模块的 path 参数指定的路径(类似于 chroot 环境),客户端只能访问模块 path 及其子目录下的文件,无法访问该路径之外的文件系统。
munge symlinks = yes            # 默认yes,修改符号链接的目标,使其看起来是相对于模块根目录的。这是 use chroot = yes 时安全处理符号链接所必需的。
max connections = 200           # 最大连接数,0为不限制
timeout = 300                   # 空闲超时时间,单位秒,0为不限制
pid file = /var/run/rsyncd.pid  # 指定 rsync 守护进程写入其进程 ID (PID) 的文件路径。
lock file = /var/run/rsync.lock # 锁文件,用于确保同一时间只有一个 rsyncd 实例运行
log file = /var/log/rsyncd.log  # 日志文件
dont compress = pattern         # 指定该模块中哪些文件不应该尝试压缩传输,避免对已经压缩过的文件进行低效的二次压缩。通常是 *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz *.7z *.mp3 *.jpg *.jpeg *.png *.avi *.mov *.ogg *.mkv 等常见的已压缩或多媒体格式。


# 模块定义/参数:只定义单个模块内的相关规则
[backup]                        # 模块名称,可以有多个,称为多模块
comment = "backup dir by noah"  # 模块描述信息,当客户端使用 rsync rsync://hostname/ 列出可用模块时会显示此描述。方便用户理解模块用途。
path = /backup                  # 共享的根目录。守护进程(以 uid/gid 身份)必须对该目录及其内容拥有适当的读(和写,如果需要上传)权限。如果 use chroot = yes,客户端只能访问此路径及其子目录下的文件。
read only = yes                 # 默认yes,控制客户端是否只能从该模块读取文件 (yes),还是也可以上传/修改/删除文件 (no)
write only = no                 # 默认no,控制客户端是否只能向该模块写入文件 (yes),还是也可以下载文件 (no)
list = yes                      # 默认yes,控制该模块是否在客户端列出可用模块时显示(例如 rsync rsync://hostname/)
auth users = rsync_backup       # 指定允许访问该模块的用户名列表(逗号或空格分隔),这里列出的用户名不是系统用户,是 rsync 模块专用的用户名。必须配合 secrets file 使用。
secrets file = /etc/rsyncd.password      # 指定存储用户名和密码的文件路径
hosts allow = 172.16.1.0/24     # 默认无(允许所有主机访问),指定允许连接该模块的客户端主机列表(逗号或空格分隔)
hosts deny = 0.0.0.0/32         # 默认无(不拒绝任何主机),指定拒绝连接该模块的客户端主机列表(逗号或空格分隔)
transfer logging = no           # 默认no,是否在日志中记录每个文件传输的开始和结束,设为 yes 会产生更详细的日志,有助于审计文件传输活动,但也会增加日志量。
refuse options = option1        # 默认无,禁止客户端在该模块上使用的 rsync 选项,例如,refuse options = delete
max connections = 300           # 设置该模块允许的最大并发连接数,覆盖全局的 max connections 设置。用于限制特定模块的资源使用。
timeout = 300                   # 该模块连接的空闲超时时间,单位秒,覆盖全局的 timeout 设置。
dont compress = pattern         # 指定该模块中哪些文件不应该尝试压缩传输,覆盖全局的 dont compress 设置。

 

创建共享目录并授权rsync服务管理(也可以直接用现有目录)

sudo mkdir /backup -p
sudo chown -R rsync.rsync  /backup/

 

创建密码文件并修改权限

# 此处的用户和密码,非系统中的用户和密码,而是rsync配置文件里定义的虚拟用户
echo "backup_user:secure_password123" | sudo tee /etc/rsyncd.secrets
sudo chmod 600 /etc/rsyncd.password

 

启动服务并设置开机自启

rsync --daemon
echo "/usr/bin/rsync --daemon" >> /etc/rc.local

 

3.3 客户端配置

生成连接服务器需要的密码文件

echo "secure_password123" | sudo tee /etc/rsyncd.secrets
sudo chmod 600 /etc/rsyncd.secrets

 

设置文件权限,权限不同则后续同步也不一样,要保留原文件属主属组的话,需授权root

# 普通用户
sudo chown amy:amy /etc/rsyncd.secrets

# root
sudo chown root:root /etc/rsyncd.secrets

 

将客户端下的文件推送至服务端

# ip后面跟的backup是服务器配置文件中的模块名,不是备份路径
rsync -avzHP /etc/hosts rsync_backup@172.16.1.41::backup --password-file=/etc/rsyncd.secrets --bwlimit=1024

# 提权,保留原文件属主属组
sudo rsync -avzHPXA /etc/hosts rsync_backup@172.16.1.41::backup --password-file=/etc/rsyncd.secrets --bwlimit=1024

 

拉取服务端下的文件

sudo rsync -avzHPXA rsync_backup@172.16.1.41::backup /backup/ --password-file=/etc/rsyncd.secrets --bwlimit=1024

 

四、补充

4.1 同步后的文件属性问题

使用普通账户

# 服务端配置uid为普通用户
uid = rsync
gid = rsync

# 客户端密码文件属主为普通用户
-rw------- 1 ops ops 19 Aug 19 11:27 rsyncd.secrets

 拉取服务端数据后,文件属主属组都为ops(客户端当前登录的用户)

rsync -av --password-file=/home/test/rsyncd.secrets backup_user@10.**.**.234::app_backup /home/test/

image

 

保留原文件属性

# 开启fake super
uid = rsync
gid = rsync
fake super = yes

# 客户端密码文件属主为root
-rw------- 1 root root 19 Aug 19 11:27 rsyncd.secrets

客户端拉取数据需提权并加上 -XA 参数

sudo rsync -avXA --password-file=/home/test/rsyncd.secrets backup_user@10.**.**.234::app_backup /home/test/

image

 

4.2 同步后软链接异常

同步后发现软链接异常,如下图。软链目录前面都加上了/rsyncd-munged/路径,导致软链路径不对

 正常应该是

 

原因:

这应该是将配置文件参数 use chroot 修改成了no,而 munge symlinks 还是默认的yes,此情况下,rsync会防止客户端通过符号链接访问 path 指定目录之外的文件系统(安全逃逸),在符号链接前面加上添加一个特殊的虚拟路径前缀 /rsyncd-munged/,防止软链被恶意使用。

 

解决:

修改配置文件参数,将参数值改成yes。

use chroot = yes
munge symlinks = yes

use chroot = yes 会在传输前将 rsync 守护进程的工作目录(及其根目录视图)切换到模块的 path 参数指定的目录。守护进程在 path 目录下运行,无法看到或访问该目录之外的文件系统(除非特殊配置,如挂载 /dev/log)。

在 chroot 环境下 (use chroot = yes),munge symlinks = yes (默认) 的行为变得安全且合理:

  • 守护进程看到的根目录 / 就是模块的 path

  • 一个指向 /etc/config.conf 的符号链接,在 chroot 环境里,实际上指向的是 $path/etc/config.conf

  • 即使客户端看到的是原始的 /etc/config.conf,当它尝试访问时:

    • 请求到达守护进程。

    • 守护进程在它的 chroot 监狱 ($path) 中解析 /etc/config.conf

    • 解析的结果是 $path/etc/config.conf

    • 守护进程只能访问 $path 下的文件,因此它操作的是 $path/etc/config.conf,而不是服务器真实的 /etc/config.conf

因此,在 use chroot = yes 时:

  • 符号链接的目标不需要被修改(munge) 成 /rsyncd-munged/... 这种奇怪的形式来防止逃逸。因为 chroot 本身已经提供了物理隔离。

  • 客户端看到的符号链接目标就是服务器上该链接在 path 目录下的原始目标值。

  • 链接在 chroot 环境内解析,指向的也是 path 目录下的某个位置(可能是有效的,也可能是无效的,但这取决于模块内的文件结构,不再是安全风险)。

 

4.3 使用rsync删除大文件

假如要在linux下删除大量文件,比如100万、1000万,像/usr/local/nginx/的nginx缓存等,那么rm -rf ./* 可能就不好用了,因为要等待很长一段时间;这时可以使用rsync来处理(替换原理)

 # 先建立一个空的文件夹:
 mkdir /tmp/null

 # 用rsync删除目标目录, (只用-a和--delete也可完成)
 rsync --delete -a -H -v --progress --stats /tmp/null/ /usr/local/nginx/

 

4.4 过滤规则

本章节摘抄自:https://zhuanlan.zhihu.com/p/441161884

4.4.1 选项

  • --include=PATTERN :设定一条包含规则,如:--include="*.php"
  • --exclude=PATTERN :设定一条排除规则,如:--exclude="*"
  • --include-from=FILE :指定一个文件,文件中一行一条包含规则,以; 或#开头的行为注释,空行被忽略
  • --exclude-from=FILE :指定一个文件,文件中一行一条排除规则,以; 或#开头的行为注释,空行被忽略
  • --filter=RULE, -f :设定一条过滤规则,可能是排除或包含规则(如:-f "- *.php" ),也可能其它类型的规则(如包含一个规则文件 -f ". ./rsync.rules"

这些选项配置的规则,其本质是一样,只是描述方式有些差异。其中 --filter=RULE, -f 选项支持完整的规则表达语法,其它的选项都可以转化为此选项的表达。举例如下:

# 以下的都是命令是完全等价的,-f 方式更简单,后文将会更多的选用 -f 的方式表达
# --include="xxx" 等价于 -f "+ xxx"
# --exclude="xxx" 等价于 -f "- xxx"
rsync -av --include="*.php" --exclude="*" src_dir/ dst_dir/
rsync -av -filter "+ *.php" -filter "- *" src_dir/ dst_dir/
rsync -av -f "+ *.php" -f "- *" src_dir/ dst_dir/

由 --include-from 或 --exclude-from 选项引入的规则文件,相当于每个规则前面自动加了 + 或-。其规则文件类内举例如下:

# --include-from 或 --exclude-from 引用的规则文件,开头没有 + 或 -
*.php
*

4.4.2 排除某些目录或文件不同步

# 排除app和vendor目录不同步
# 注意此命令会排除名称是app或vendor的目录或文件,因为模式规则1
rsync -av -f '- app' -f '- vendor' src_dir/

# 此命令则只排除 src_dir 一级子目录中的 app 和 vendor 
rsync -av -f '- /app/' -f '- /vendor' src_dir/

# 排除更深层次的子目录
rsync -av -f '- /app/Admin' -f '- /vendor' src_dir/

# 排除隐藏文件/目录 和 php文件
# 因为模式规则9,10,4,模式`.*`相当于是要求路径最后的名称(文件或目录)必须是`.`开头
rsync -av -f '- .*' -f '- *.php' src_dir/

排除多个目录

rsync -av --exclude-from 'exclude.txt' src_dir/ dst_dir/

exclude.txt内容:

# test 跟 test/ 都是排除相对路径下的test目录,都能实现,具体区别尚不清楚
test
test/
*.php

4.4.3 只同步指定的子目录

以下所有命令均等价,只是实现思路不同。效果都是:只同步config目录(包括所有子目录和文件)

# 命令4.2-1:使用了模式规则1、4
# 因模式规则1,-f '- /*'规则排除了str_dir目录下出config外所有的文件和子目录
# 递归扫描config目录时,因不命中任何规则,所有子目录和文件都被默认包含
rsync -av -f '+ config' -f '- /*'  src_dir/

# 命令4.2-2:使用了模式规则4、5、9
# -f '+ config'匹配config目录并包含
# -f '+ config/**' 匹配config目录下所有的子目录和文件的路径,包含。模式规则5
# 其余所有的路径被 -f '- *'匹配,排除。模式规则4、9
rsync -av -f '+ config/**' -f '+ config' -f '- *'  src_dir/

# 命令4.2-3:
# -f '+ config/***' 匹配config目录以及其所有子目录和文件。规则6
rsync -av -f '+ config/***'  -f '- *'  src_dir/

# 命令4.2-4:
# 使用修饰符!取反,排除了config目录以及其所有子目录和文件路径以外的路径
# 相当于只同步config目录
rsync -av -f '-! config/***' src_dir/
只同步多个一级子目录(只同步config、app目录(包括所有子目录和文件))
# 注意两条命令的排除规则是不同的,可以参考体会一下模式规则1
rsync -av -f '+ config' -f '+ app' -f '- /*'  src_dir/
rsync -av -f '+ config/***' -f '+ app/***'  -f '- *'  src_dir/
只同步更深层级的子目录

模仿只同步一级子目录的写法,可能会直接把命令写成rsync -av -f '+ app/Admin' -f '- /*' src_dir/。但此命令并不能按预期工作。原因是rsync扫描到app路径时,并不能命中-f '+ app/Admin'规则,然后就后面的规则排除掉了。然后就没然后了,此命令不会同步任何文件。

明白这个问题后,修正它,然后就可写出只同步app/Admin子目录(包含所有子目录和文件)的命令了,以下都是:

# 命令4.2-5:
# 扫描到一级子目录app时,其路径并不会和规则 -f '+ app/Admin/' 匹配,因为模式规则9
# app 路径是有规则 -f '+ app' 命中包含的。此规则若去掉,则此命令不会同步任何文件和目录
# -f '- /*' -f '- /*/*' 两条规则是排除所有未被前面规则包含的一级子目录/文件和二级子目录/文件
# app/Admin/ 下的子目录/文件将不会在命中规则,默认包含
rsync -av -f '+ app/Admin/' -f '+ app' -f '- /*' -f '- /*/*' src_dir/

# 命令4.2-6:效果同命令3-5
# 思路同命令4.2-4
rsync -av -f '+ app' -f '-! app/Admin/***' -f '- /*' src_dir/

# 命令4.2-6:效果同命令3-6,思路则不同
# -av -f '+ app'规则包含app
# -av -f '+ app'规则包含app/Admin/目录及所有子目录和文件
# 其余路径由 -f "- *" 排除
rsync -av -f '+ app' -f '+ app/Admin/***' -f "- *"   src_dir/

# 命令4.2-7
# -f '-! app/***'规则使用取反,只保留app子目录
# -f '+ app/Admin/' 包含app/Admin/目录,其余二级子目录由规则-f "- /*/*"排除
# app/Admin/目录下所有子目录和文件,无规则命中,保留
rsync -av -f '-! app/***' -f '+ app/Admin/' -f "- /*/*"  src_dir/
只同步多个深层级的子目录

与只同步一个深层级子目录类似,也可以写出很多不同的命令。但问了减少出错,建议使用命令4.2-6的思路,比较简洁。给深层的子目录的所有父级目录都添加好包含规则,然后深层子目录添加***的包含规则,最后是一条排除规则。

rsync -av -f '+ /app' -f '+ /app/Admin/***' -f '+ /vendor' -f '+ /vendor/psy' -f "- *"   src_dir/

4.4.4 快速复制目录结构

有时需要需要创建一个目录,其子目录层次结构与另一个目录结构一样,但不需要其中的文件,这可以用rsync命令快速完成

# 使用了修饰符!取反,排除了目录以外的路径。模式规则1
rsync -av -f '-! */' src_dir/ dst_dir/

 

4.5 无密码两机器同步(慎用)

服务端配置如下,启动rsync服务

uid = root
gid = root
use chroot = yes
strict modes = false
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock

transfer logging = true
log format= "%o [%a] %m (%u) %f %l %b %c"

reverse lookup = no
ignore errors = true
read only = false
hosts allow = 10.35.0.0/16,10.0.0.0/8
strict modes = yes
list = false
max connections = 100
timeout = 1800

[data]
path = /data
ignore errors

客户端拉取:

rsync -avzHP 10.10.10.10::data /data

 

posted @ 2022-01-04 18:26  心恩惠动  阅读(337)  评论(0)    收藏  举报