Rsync 不仅可以采用 SSH 加密传输,而且可以运行守护进程,无加密的方式。
因为要让传输过来的文件具有指定的属主和属组,因此本文选用 Rsync 协议,也就是守护进程方式。
目录设置
因为是 Web 项目,所以要有站点根目录。根据计划,通过 Rsync 由电脑本地上传到服务器。
这里新建一个目录,并设置权限(要与 Nginx(Apache)等指定的一样)。
# 保证属组可读写
umask 002
mkdir -p /var/www/wordpress/htdocs
chown nginx:nginx -R /var/www/wordpress/htdocs
配置文件
Rsync 服务端的守护进程运行时配置选项在 /etc/rsyncd.conf。
这些选项参数影响身份验证、访问、日志和可用模块。
运行 Vi 编辑器来编辑:vi /etc/rsyncd.conf。
原始的 Rsync 服务器设置如下所示:

从上图可知悉,当前的 Rsync 器并没有生效,因为所有配置都注释着。
配置文件的格式
该文件由模块和参数组成,模块之外是全局参数,全局参数影响着守护进程的操作和行为,也影响着每个模块,然而一些参数在模块中如果设置的话会覆盖相应全局参数的值。
模块以方括号的模块名称开始,一直持续到下一个模块开始。模块包含的参数格式 name = value。
参数中只能有一个等号,等号、模块和参数名称中周围和内部的空白会被忽略。比如:参数 secrets file = /etc/rsyncd.passwd,与 secretsfile=/etc/rsyncd.passwd 无区别。
任何行以 “#” 开头都被忽略,空行(即使仅包含空格)也是如此。
等号后面的值都是字符串(不需要引号)或布尔值,可以是 yes/no、1/0,或者是 true/false。布尔值中的大小字不敏感。
经本文修改后的配置
我们就把原有选项的注释取消掉,然后再修改和添加一些选项进去,让服务端正常启动并可用。
修改后的服务端配置如下:
uid = nobody
gid = nobody
use chroot = yes
max connections = 10
pid file = /var/run/rsyncd.pid
log file = /var/log/rsyncd.log
exclude = lost+found/
transfer logging = yes
timeout = 800
ignore nonreadable = yes
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2 *.tar.xz *.tar.gz
[wphtmod]
uid = nginx
gid = nginx
path = /var/www/wordpress/htdocs
read only = false
write only = true
list = true
auth users = wprsync, wprsync2
secrets file = /etc/rsyncd.passwd
strict modes = false
全局参数详解
-
uid:默认是 nobody。 运行守护进程的系统用户 ID,可以是 ID,也可以是用户名。
传输成功后所属用户就是此用户。
-
gid:默认是 nobody。gid 是系统用户组的 ID,也可以是用户组的名称。
传输成功后所属组就是此用户组。
无论是 uid 或者是 gid,都可以全局设置和在模块中设置,在模块中的设置会覆盖全局设置。
-
use chroot:如果该参数设置为 “yes”,那么在传输之前先把目录切换到模块中设置的 path 参数指定的目录。
此举避免了一些安全漏洞。
它需要 root 权限。
-
max connections:允许的最大连接数,默认为 0,表示没有限制。
-
pid file:指定守护进程的 PID 文件所在路径。
-
log file:指定日志路径。
-
exclude:排除要传输的目录,模式之间用空格隔开。
也可以使用“include”参数来覆盖“exclude”参数的效果。
-
transfer logging:是否启用日志来记录 Rsync 的上传下载。值为 “yes”或“no”。
-
timeout:指定超时时间。如果在指定时间内没有数据传输, Rsync 会直接退出。单位是秒,默认值为 0 表示永不超时。
-
ignore nonreadable:是否忽略用户没有访问权限的文件。值为 “yes”或“no”。
-
dont compress:不压缩传输的文件列表。
模式之间用空格隔开,支持通配符 * 来指定模式,凡是匹配这些模式都不压缩便传输。
此参数也可在模块中使用。
其他全局参数:
-
hosts allow:用于指定允许哪些 IP 或网段客户端访问。可以填写 IP、网段、主机名、域下的主机,IP 之间用空格隔开。默认允许所有人访问。
-
hosts deny:用户指定的哪些 ip 或网段客户端不允许访问。
如果 hosts allow 和 hosts deny 具有相同的匹配结果,则客户端最终无法访问。
如果客户端的地址既不在 hosts allow 中也不在 hosts deny 中,则允许客户端访问。
默认情况下,所有人可访问。
以上两个参数在模块中亦可一模一样地使用。
模块参数设置
Rsync 的模块配置可以分别指定服务于不同的目录、属主等选项。
-
wphtmod:模块名,可自定义。
-
uid:默认是 nobody。
作用与上方全局配置是一样的。
由于本文中在该服务端仅服务于站点目录,所有要与服务器软件/PHP-FPM指定的用户组一致,因为这才能修改和写入。
这里的服务器软件运行用户是 nginx,因此该参数除了设置成 nginx,就只能是 root 用户了。说真的,用 root 确实有安全隐患。
-
gid:默认是 nobody。gid 可以是系统用户组的 ID 或者名称。设为 nginx 的原因与 uid 一致。
作用与上方全局配置是一样的。
-
path:指定服务器目录路径。
-
read only:此参数确定客户端是否能够上传。
如果该参数为 true,则表示只读,任何尝试的上传都将失败。
如果参数值为 false,那么只要权限允许,就可以进行上传。默认情况下,所有模块都是只读的。
-
write only:此参数确定客户端是否能够下载。
如果该参数为 true,则表示仅写,任何尝试的下载都将失败。
如果参数值为 false,那么如果权限允许,则可以进行下载。默认情况下,此参数将被禁用。
-
list:当客户端要求列出可用模块时,此参数确定是否列出此模块。默认为 true。
-
auth users:此参数指定以逗号和/或空格分隔的授权规则列表。
在最简单的形式中,可以列出将被允许连接到此模块的用户名。
用户名不需要存在于本地系统中。规则可能包含 Shell 通配符,这些通配符将与客户端提供的用于身份验证的用户名相匹配。
多个授权用户名可以用逗号+空格隔开。如:auth users = wprsync, wprsync2 。
如果设置了“auth users”,则客户端将被要求提供用户名和密码以连接到模块。
纯文本用户名和密码存储在 secrets file 参数指定的文件中。
默认情况下,所有用户都可以在没有密码的情况下进行连接(这被称为“匿名 Rsync ”)。
-
secrets file:指定一个纯文本文件,用来储存与 auth users 授权用户列表中一一对应的密码。
其内容格式如下:
username1:passowrd1
username2:passowrd2
在这里,密码文件位于: /etc/rsyncd.passwd。
此权限要是 600,把属主更改为 Rsync 守护进程的运行用户,并且只能属主可读写。
-
strict modes:确定是否检查密码文件的权限。
如果 strict modes 为 true,那么除了 Rsync 守护程序运行的用户 ID 之外,任何用户 ID 都不能读取用户名-密码对。
如果参数为 true,则不执行检查。
默认为 true。
添加此参数是为了适应在 Windows 操作系统上运行的 Rsync 。
...其实还有很多参数可供配置,由于篇幅原因,就不此赘述了
更多的 rsyncd.conf 配置请阅读参考命令行文档 man rsyncd.conf。
守护进程
通过选项 --daemon 来启动守护进程:
sudo rsync --daemon
当然也可以把整个启动命令写进 rsyncd.service。
修改服务器的默认端口
在配置文件中修改未果,于是根据文档,在 Rsync 的守护进程服务配置中修改:
cat>/lib/systemd/system/rsyncd.service<<EOF
[Unit]
Description=fast remote file copy program daemon
ConditionPathExists=/etc/rsyncd.conf
[Service]
EnvironmentFile=/etc/sysconfig/rsyncd
# ExecStart=/usr/bin/rsync --daemon --no-detach "\$OPTIONS"
# 将上行修改为:
ExecStart=/usr/bin/rsync --daemon --port=6666 --no-detach "\$OPTIONS"
[Install]
WantedBy=multi-user.target
EOF
将端口修改为 “6666”。
执行以下命令使修改生效:
sudo systemctl daemon-reload
sudo systemctl restart rsyncd
sudo systemctl status -l rsyncd
以上修改网络端口号仅适用于 SELinux 禁用状态下。
防火墙开放端口允许进入
-
FirewallD 防火墙(如果有的话):
sudo firewall-cmd --permanent --add-port=6666/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-all
-
外部或硬件防火墙:
一些主机提供商会有自己的网络防火墙设置,设置界面基本上是很易用的,读者只需要开放入栈的 TCP 6666 端口即可。
同步本地目录到远程
rsync -v -a --delete --exclude-from=/path/to/exclude/file.list \
--password-file=/path/to/rsync_passwd /path/to/htdocs/ rsync://wprsync@192.168.1.100:6666/wphtmod/
解析一下上述命令的一些参数和值:
-
-v:表示输出传输过程中输出的一些数据,如若没有指定,那么就没有任何信息输出到屏幕上,基本上等于静默模式;
-
-a:表示保留创建、修改和访问时间等的元信息,以及表示递归遍历访问;
-
--delete:当源被删除,在同步后,远程也同步删除,这也是 Rsync 增量备份的基础之一;
-
--exclude-from:从文件中读取排除的模式。
当模式匹配到时,对应的文件名将会被忽略。每行代表一个模式,可以有 * 号作为通配符,目录后面不用跟着斜杠。
像这样:
.git*
node_modules
package.*
.phpactor.json
*.cache
-
--exclude:与 --exclude-from 一样,都是设定要排除的模式。
不同的是其值是一个字符串(仅一个模式的时候),或者有多个值,用花括号 {} 包裹着的字符串列表。
比如: {'file1.txt', 'dir1/*', 'dir2'}。
-
--password-file: 指定在服务器端由参数 secrets file 指定的密码文件中的密码部分(每行的冒号右边部分)作为内容的本地文件。
只有一行才是密码,其余行忽略。
一般赋予 600 权限;
-
/path/to/htdocs/:表示源目录所在位置,它位于本地计算机上;
如果路径后面没有斜杠,那么表示将 htdocs 本身上传到指定路径中,而不是上传 htdocs 里面的文件(不包括 htdocs 本身)。
它将上传到在上文所指定的位置 /var/www/wordpress/htdocs。
于是,如果路径后面没有斜杠,上传后,将放在 /var/www/wordpress/htdocs/htdocs,这不是作者想要的。
这就是源目录后面有斜杠与没有斜杠的区别。
这个问题读者做做实验就明白了。
-
rsync://wprsync@192.168.1.100:6666/wphtmod/:
-
rsync://:表示用 rsync 协议;
-
wprsync:表示服务端在模块中由auto users设置的授权用户名,此用户名不是系统的用户名,只是用来验证登录远程 Rsync 服务的名字;
-
192.168.1.100:目标服务器的 IP 地址,指向该 IP 地址的域名也行;
-
6666:表示 Rsyncd 接收文件数据的本地网络端口,指定未分配的其他数字也可以;
-
wphtmod:模块名,这也是由服务端设置的,决定上传到哪个位置,在服务端模块中由 path 指令指定。
根据以上的各种参数配置,本地 htdocs 将会 上传到服务器的 /var/www/wordpress/,即形成站点根目录 /var/www/wordpress/htdocs 。
更多的参数配置请参阅命令行文档: man rsync。
踩坑实录
在要进行增量备份的时候,千万不要在源目录路径的后面加上通配符(像下面的命令那样),若是做了这件事,--delete 此参数就不起作用了,读者切记!
rsync -v -a --delete --exclude-from=/path/to/exclude/file.list\
--password-file=/path/to/rsync_passwd /path/to/htdocs/* rsync://wprsync@192.168.1.100:6666/wphtmod/
这时候用 /path/to/htdocs/ 代替 /path/to/htdocs/星号 才是想要的效果:
rsync -v -a --delete --exclude-from=/path/to/exclude/file.list\
--password-file=/path/to/rsync_passwd /path/to/htdocs/ rsync://wprsync@192.168.1.100:6666/wphtmod/