服务器其它

关注公众号 jb51net

关闭
首页 > 网站技巧 > 服务器 > 服务器其它 > rysnc命令过滤规则

rysnc命令过滤规则入门教程

投稿:mdxy-dxy

本文针对 rsync 过滤规则主要讲解了4大块内容:配置方法、内部运行方式、规则语法和使用技巧举例,其内容都是来自官方手册和实操测试,若有谬误,欢迎大家批评指正,也欢迎大家在评论区沟通交流 rsync 的各种经验和技巧

0、前言

rsync 命令的过滤规则功能非常强大,但网上几乎没有详解此主题的资料,让人学习和理解有一定的难度。官网文档 和man rsync手册是英文的,没有什么示例说明,不好理解。即使有人翻译了手册,理解起来也是有一定的难度。

故而有了此教程,结合实际命令对过滤规则的相关概念、逻辑和使用技巧做一个比较透彻的讲解。希望有兴趣学习的朋友,可以快速的入门,节省时间。为什么说是入门呢?因为 rsync 的过滤规则相关内容里,还包含了一些高级技巧,个人感觉实际项目中用到的机会比较少,并未包含在此教程里。

本教程主要分为以下三部分:

1、概述

1.1 什么是 rsync 的过滤规则?

rsync 过滤规则是用于定义哪些文件要传输(包含某些文件)哪些文件不要传输(排除某些文件)的一些规则。这些规则可以直接写在命令参数里,也可以写在规则文件里,然后由命令引用。例如:

# 命令1.1-1:规则直接写在命令参数里
# --include="*.php" --exclude="*" 这两个参数配置了两条过滤规则
# 此命令将会只同步src_dir目录下的php文件(不包含子目录的)
rsync -av --include="*.php" --exclude="*" src_dir/ dst_dir/

# 命令1.1-2:通过规则文件配置规则
# rsync.rules 为规则文件,可以使用相对路径或绝对路径
rsync -av -f ". ./rsync.rules" src_dir/ dst_dir/
rsync -av -f ". /www/rsync.rules" src_dir/ dst_dir/

rsync.rules 规则文件的内容如下(具体语法后文说明):

# 只同步php文件
+ *.php
- *

1.2 配置过滤规则的方式有哪些?

与过滤规则有关的选项包括主要有:

这些选项配置的规则,其本质是一样,只是描述方式有些差异。其中 --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
*

1.3 过滤规则的工作方式

所有的过滤规则配置最终在 rsync 内部会形成一个有序的规则列表,在命令行中靠前选项,其规则的排序也靠前。随着要传输的(文件/目录路径)列表的构建,针对每个路径,rsync 会依次读取有序规则列表中的规则进行检查。当第一个规则匹配成功后,立即进行操作(包含或排除),并停止后面规则的检查;若所有规则都不不匹配,此路径默认为包含。若有递归选项时(如-r -a),如果子目录被规则排除,那么 rsync 不会递归检查此目录的内容了,也就是此目录下的文件和目录不会进行规则过滤也不会传输,相当于整个子目录都排除了。简单总结如下:

举例如下:

# 此命令会同步src_dir目录下的所有php文件(不包含子目录的)
# 因为src_dir目录下每个文件和目录路径都会先由 -f "+ *.php" 规则检查,php文件符合此规则就被包含了,后面的 -f "- *" 规则不会检查了
# 其余类型的文件和子目录,不符合第一个规则,继续检查第二个规则时,都被排除了
# 子目录被排除后,其中即使有php文件,也不会被检查,所以此命令不会同步src_dir目录下子目录中的php文件
rsync -av -f "+ *.php" -f "- *" src_dir/ dst_dir/

# 调换两个参数的顺序,则完全不一样了
# 此命令将不会同步任何文件和目录
# 因为第一条规则把所有文件和目录到排除了,第二条规则没有机会生效
rsync -av -f "- *" -f "+ *.php" src_dir/ dst_dir/

# 此命令会同步src_dir目录下的所有php文件(包含子目录的)
# 规则 -f "+ */" 会匹配并包含所有子目录路径,所以 rsync 会检查所有的子目录,然后其中的php文件被包含了
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/

1.4 配置过滤规则的语法

过滤规则的语法如下:

操作 [匹配模式]
操作,修饰符 [匹配模式]

操作:是诸如+(包含)和-(排除)。还有之前引用规则文件(-f ". ./rsync.rules")的.号,其意义是包含规则文件的操作。还有其它的一些后文详细说明。

修饰符:可用于改变规则的一些行为方式,后文详细说明。

匹配模式:用于匹配字符串的模式,类似正则表达式,可用于检查字符串是否符合某种模式。若符合就说是匹配的,或说命中了。中括号表示匹配模式是可选的,因为某些特殊的操作,没有匹配模式。

操作和匹配模式之间的空格必须是一个英文空格,也可以使用_字符代替,这在命令行中直接写规则时,可以省略引号。例如:

# 以下两条命令完全等价
# 省略引号的写法应注意其中的*号被意外扩展为路径了
# 建议使用空格加引号的写法,更清晰和安全
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/
rsync -av -f +_*.php -f +_*/ -f -_* src_dir/ dst_dir/

1.5 测试方法

若需要反复修改命令进行测试,按照实际同步的方式,可能需要不断的删除目标目录的文件,这多少有点不方便。有一个解决办法就是,稍微改变一下 rsync 命令,去掉目标目录不写,则表示不实际同步数据,只列出需要同步的文件/目录列表。例如:

# 原命令
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/ dst_dir/

# 修改后
# 此命令并不会实际同步数据,只会输出要同步的文件/目录列表
rsync -av -f "+ *.php" -f "+ */" -f "- *" src_dir/

2、操作和修饰符

2.1操作

规则类型是由操作决定的,操作不同可以看作是规则类型不同。操作一共有以下9种,每种操作都有对应的标识,分为长标识和短标识,一般配置时都是使用短标识

| 序号 | 长标识 | 短标识 | 操作说明 | 说明 | | ---- | --------- | ------ | ------------------------------ | ---------------------- | | 1 | exclude | - | 排除操作 | 排除符合匹配模式的路径 | | 2 | include | + | 包含操作 | 包含符合匹配模式的路径 | | 3 | merge | . | 引入规则文件 | 参考:命令1.1-2 | | 4 | dir-merge | : | 指定每个目录里要合并的规则文件 | 针对传输目录,不常用 | | 5 | hide | H | 指定从传输中隐藏文件的模式 | | | 6 | show | S | 指定某些文件不会被隐藏 | | | 7 | protect | P | 指定某些文件受保护不被删除 | | | 8 | risk | R | 指定某些文件不受保护 | | | 9 | clear | ! | 清除当前包含/排除列表 | 无匹配模式 |

最基本也是最常用的操作就是前3个,比较好理解,之前的示例里已经有说明,这里不再重复。

2.2 修饰符

修饰符只可用于包含/排除操作(+/-),一共有以下7种。当操作使用短标识是,中间的逗号是可以省略的。

1.修饰符/

包含/排除操作后面的匹配模式,本来是针对传输目录的相对路径进行匹配。加了此修饰符后,会把相对路径转换为绝对路径后进行匹配,匹配的方式和规则保持不变。例如:

# 假设 src_dir 的绝对路径未为:/www/src_dir

# 命令2.2-1:此命令将同步src_dir下的所有php文件,但不包括admin.php
# 当扫描到admin.php文件时,其相对路径是 'admin.php'。转化为绝对路径为 '/www/src_dir/admin.php'
# 使用 '-f "-/ src_dir/admin.php"' 规则检查时,匹配(为什么匹配请看后文匹配模式),然后排除。
rsync -av  -f "-/ src_dir/admin.php" -f "+ *.php"  -f "- *" src_dir/

# 同理此命令效果相同
rsync -av  -f "-/ /www/src_dir/admin.php" -f "+ *.php"  -f "- *" src_dir/

2.修饰符!

表示否定,对匹配结果进行取反,把匹配成功当做匹配失败,把匹配失败当做匹配成功。例如:

# 此命令只同步src_dir下的php文件
# 扫描src_dir目录下的文件和目录时,php文件以外的目录和文件都匹配失败,取反变成匹配成功,排除
# 而php文件最终变成匹配失败,算未命中任何规则,默认保留
rsync -av -f "-! *.php"  src_dir/

# 经测试,/和!两个修饰符可以同时使用
# 修改命令2.2-1
# 此命令将只同步admin.php文件
rsync -av  -f "-/! src_dir/admin.php" -f "+ *.php"  -f "- *" src_dir/

# 但以下命令报错了
rsync -av  -f "-!/ src_dir/admin.php" -f "+ *.php"  -f "- *" src_dir/

# 但改为单引号后正常了,可能是双引号中的某些字符被意外解析了
# 也就是多个修饰符时,顺序不影响
# 这又是一条经验,如非必要,参数请用单引号
rsync -av  -f '-!/ src_dir/admin.php' -f "+ *.php"  -f "- *" src_dir/

3.修饰符C

未仔细研究,略过

4.修饰符s

未仔细研究,略过

5.修饰符r

未仔细研究,略过

6.修饰符p

未仔细研究,略过

7.修饰符x

未仔细研究,略过

3、匹配模式

包含和排除规则,都有一个匹配模式,如 过滤规则- *.php中的字符串*.php就是此规则的匹配模式。用于检查匹配传输路径(要同步的原目录中文件或目录的相对路径,有修饰符/时为绝对路径)。匹配模式就是描述路径特征的一个字符串,如 *.php描述的就是路径末尾的名称()必须是.php结尾。功能和用法类似正则表达式,但比正则表达式简单。

传输路径:是指 src_dir 中文件或目录的相对路径,格式类似如下:

server.php
services.php
session.php
view.php
config/
config/services.php
config/session.php
config/view.php
routes/
routes/api.php
routes/channels.php
routes/console.php
routes/web.php

匹配模式将是和这些路径进行匹配。

关于匹配模式,我一共总结了10条模式规则:

以下举例说明各条规则的使用:

4、使用场景举例

4.1 场景:排除某些目录或文件不同步

此需求比较简单,因为默认包含所有路径,只需设定排除规则,排除对应的目录或文件即可

# 排除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/

4.2 场景:只同步指定的子目录

因为传输路径若无规则命中默认是包含(同步),所以若要实现只同步指定目录,需主动写过滤规则排除不需要同步的路径。整体思路就是,先写规则包含要同步的路径,然后排除其余路径。先比较简单的只同步一级子目录开始

只同步一级子目录

以下所有命令均等价,只是实现思路不同。效果都是:只同步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.3 场景:快速复制目录结构

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

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

5、总结

本文针对 rsync 过滤规则主要讲解了4大块内容:配置方法、内部运行方式、规则语法和使用技巧举例。其内容都是来自官方手册和实操测试,若有谬误,欢迎大家批评指正。也欢迎大家在评论区沟通交流 rsync 的各种经验和技巧。

另外还需强调的是,这个不是 rsync 过滤规则的全部内容,例如操作和修饰符的讲解并不完整,命令中的其它一些与过滤有关的选项(如:--prune-empty-dirs)也未涉及。若有更高级功能的需求,请大家查阅官方手册。

阅读全文