Linux 下 Rsync 文件同步与增量备份

By | 最新修改:2024-08-17

前言

什么是 Rsync

Rsync ,Remote Synchronous,“远程同步”的意思,是一款开源自由的 Linux 文件传输软件,通常用作为增量备份的工具。它 可以本地与本地不同目录间互相同步,也可以本地与远程服务器端进行文件同步,更可以远程对远程进行文件增量备份

这里的同步不是实时同步,要想实时,那么要用到其他工具与之协同。

Rsync 还可以配合 inotify、sersync 和 Crontab 进行实时、定时或时间间隔式的文件同步

为什么要同步文件

由于作者要在本地 Ubuntu 系统开发 WordPress 插件,然后将代码同步到服务器端的 PHP-FPM 和 Nginx 执行。

为什么是 Rsync

用 SCP 来传输不太方便,不仅没有提供增量备份,并且 Rsync 可以设置指定传输过来的文件属主和属组,毕竟 Nginx 需要读写其站点目录,这些都是 SCP 没有的。

经过一番百度,就接触到 Rsync ,发现 Rsync 的功能比较让作者满意。

本文的主要内容和写作目的

本文介绍 如何配置 Rsync 服务器端、(远程)目录权限,以及本地与服务器同步的参数配置

作者写下这篇文章的目的在于让读者避免踩坑。 Rsync 这个软件就这么简单,就是这么配置和使用的,并没有多复杂和可怕,这是作者这两天踩坑踩出来的感悟。

所需要的依赖:

服务器端:CentOS 7 X64

客户机:Ubuntu 20.04 LTS+ 版本

Rsync 的服务器与客户端

本文对 CentOS 的操作都是以 root 的身份

如果用其他的一般系统用户,请用 sudo 命令提权


安装 Rsync

CentOS 7 安装

yum install -y rsync

Ubuntu 安装

sudo apt-get install -y rsync

Arch Linux 安装

sudo pacman -S rsync

Rsync 服务器端

Rsync 不仅可以通过 SSH 加密传输文件,而且可以在自己的服务器端守护进程, 可以进行无加密的传输

因为要让传输过来的文件具有指定的属主和属组,因此本文选用 Rsync 协议,也就是其服务器端提供的传输服务,虽然无加密,但是这方便。

目录设置

因为是 Web 项目,所以要有站点根目录。根据计划,站点目录会通过 Rsync 由电脑本地上传到服务器。

这里新建一个站点根目录,并设置权限。

# 保证属组可读写
umask 002
mkdir -p /var/www/wordpress/htdocs
chown nginx.nginx -R /var/www/wordpress/htdocs

站点根目录在 /var/www/wordpress/htdocs 目录。

服务器的配置文件

Rsync 服务端的守护进程运行时配置文件在 /etc/rsyncd.conf

此文件中的参数影响身份验证、访问、日志和可用模块。

运行 Vim 编辑器编辑该文件:vim /etc/rsyncd.conf

原始的 Rsync 服务器设置如下所示:

Rsyncd配置文件原样

从上图可知悉,当前的 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

全局参数详解

  1. uid:默认是 nobody。 运行守护进程的系统用户 ID,可以是 ID,也可以是用户名。

    文件传输成功后所属用户就是此用户。

    如果设为 root,那么文件上传到服务器后,这些文件的属主默认会是 UID 为 1000 的用户。

  2. gid:默认是 nobody。gid 是系统用户组的 ID,也可以是用户组的名称。

    文件传输成功后所属组就是此用户组。

    uid 一样,如果设为 root,那么文件上传到服务器后,这些文件的属组默认会是 GID 为 1000 的用户。

    无论是 uid 或者是 gid,都可以全局设置和在模块中设置,在模块中的设置会覆盖全局设置。

  3. use chroot:如果该参数设置为 “yes”,那么在传输文件之前先把目录切换到模块中设置的 path 参数指定的目录。

    此举避免了一些安全漏洞。

    它需要 root 权限。

  4. max connections:允许的最大连接数,默认为 0,表示没有限制。

  5. pid file:指定 Rsync 守护进程的 PID 文件所在路径。

  6. log file:指定服务器日志文件。

  7. exclude:排除要传输的目录/文件,模式之间用空格隔开。

    也可以使用“include”参数来覆盖“exclude”参数的效果。只有一个 “include”参数可以应用于给定的模块。

  8. transfer logging:是否启用日志来记录 Rsync 的上传下载。值为 “yes”或“no”。

  9. timeout:指定超时时间。如果在指定时间内没有数据传输, Rsync 会直接退出。单位是秒,默认值为 0 表示永不超时。

  10. ignore nonreadable:是否忽略用户没有访问权限的文件。值为 “yes”或“no”。

  11. dont compress:不压缩传输的文件列表。

    文件/模式之间用空格隔开,支持通配符 * 来指定模式,凡是匹配这些模式的文件都不压缩便传输。

    此参数也可在模块中使用。

其他全局参数:

  1. hosts allow:用于指定允许哪些 IP 或网段客户端访问。可以填写 IP、网段、主机名、域下的主机,IP 之间用空格隔开。默认允许所有人访问。
  2. hosts deny:用户指定的哪些 ip 或网段客户端不允许访问。

    如果 hosts allowhosts deny 具有相同的匹配结果,则客户端最终无法访问。

    如果客户端的地址既不在 hosts allow 中也不在 hosts deny 中,则允许客户端访问。

    默认情况下,所有人可访问。

以上两个参数在模块中亦可一模一样地使用。

模块参数设置

Rsync 配置的模块决定服务器分别由哪个目录路径接收远程传输过来的文件、是否对该目录可读、可写,以及指定授权用户名和授权密码。当然还有其他的参数。

  1. wphtmod:模块名,可自定义。
  2. uid:默认是 nobody

    作用与上方全局配置是一样的。

    由于在该服务端仅服务于 Nginx 站点目录的文件,所有要与 Nginx 运行用户相一致,因为这才能修改和写入站点文件。

    这里的 Nginx 运行用户是 nginx,因此该参数除了设置成 nginx,就只能是 root 了。说真的,用 root 确实有安全隐患。

    在传输文件到服务器时,若是需要更改文件属主和属组,那么此值必需为 root

  3. gid:默认是 nobody。gid 是系统用户组的 ID,也可以是用户组的名称。设为 nginx 的原因与 uid 一致。

    作用与上方全局配置是一样的。

  4. path:指定路径去放置来自远程的文件。

  5. read only:此参数确定客户端是否能够上传文件。

    如果该参数为 true,则任何尝试的上传都将失败。

    如果参数值为 false,那么如果守护程序端的文件权限允许,则可以进行上传。默认情况下,所有模块都是只读的。

  6. write only:此参数确定客户端是否能够下载文件。

    如果该参数为 true,则任何尝试的下载都将失败。

    如果参数值为 false,那么如果守护程序端的文件权限允许,则可以进行下载。默认情况下,此参数将被禁用。

  7. list:当客户端要求列出可用模块时,此参数确定是否列出此模块。默认为 true

  8. auth users:此参数指定以逗号和/或空格分隔的授权规则列表。

    在最简单的形式中,可以 列出将被允许连接到此模块的用户名

    用户名不需要存在于本地系统中。规则可能包含 Shell 通配符,这些通配符将与客户端提供的用于身份验证的用户名相匹配。

    多个授权用户名可以用逗号+空格隔开。如:auth users = wprsync, wprsync2

    如果设置了“auth users”,则客户端将被要求 提供用户名和密码以连接到模块

    纯文本用户名和密码存储在 secrets file 参数指定的文件中。

    默认情况下,所有用户都可以在没有密码的情况下进行连接(这被称为“匿名 Rsync ”)。

  9. secrets file:指定一个纯文本文件,用来储存与 auth users 授权用户列表中一一对应的密码。

    其文件内容格式如下:

    username1:passowrd1
    username2:passowrd2
    

    在这里,密码文件位于: /etc/rsyncd.passwd

    此文件权限要是 600,把文件属主更改为 Rsync 守护进程的运行用户,并且只能属主可读写。

  10. strict modes:确定是否检查密码文件的权限。

    如果 strict modestrue,那么除了 Rsync 守护程序运行的用户 ID 之外,任何用户 ID 都不能读取密码文件。

    如果参数为 true,则不执行检查。

    默认为 true

    添加此参数是为了适应在 Windows 操作系统上运行的 Rsync 。

…其实还有很多参数可供配置,由于篇幅原因,就不此赘述了

更多的 rsyncd.conf 配置请阅读参考命令行文档 man rsyncd.conf

Rsync 的守护进程

通过使用 rsync 启动选项 --daemon 来启动 Rsync 守护进程。

当然也可以把整个启动命令写进 rsyncd.service 文件中。

如果想使用 chroot,在此情况下,若要 Rsync 修改服务器端目录的属主用户,那么 编号低于 1024(默认是 873)的端口或设置文件所有权,则守护程序必须以 root 权限运行。否则,它仅具有读取和写入适当的数据、日志和锁定文件的权限。

修改服务器的默认端口

在配置文件中修改未果,于是根据文档,在 Rsyncd 的守护进程服务配置文件(位于 /lib/systemd/system/rsyncd.service )中修改:

[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

将端口修改为 “6666”。

执行以下命令使修改生效:

systemctl daemon-reload
systemctl restart rsyncd
systemctl status -l rsyncd

以上修改网络端口号仅适用于 SELinux 禁用状态下。

防火墙开放端口允许进入

  1. FirewallD 防火墙:
    firewall-cmd --permanent --add-port=6666/tcp
    firewall-cmd --reload
    firewall-cmd --list-all
    
  2. 外部或硬件防火墙:

    一些主机提供商会有自己的网络防火墙设置,设置界面基本上是很易用的,读者只需要开放入栈的 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/

解析一下上述命令的一些参数和值:

  1. -v:表示输出传输过程中输出的一些数据,如每个文件路径和名称等;如没有指定,那么就没有任何信息输出到屏幕上, 基本上等于静默模式
  2. -a:表示保留每个文件的创建、修改和访问时间等的元信息,以及表示递归遍历访问;

  3. --delete:源目录删除,在同步后,远程目录也会删除相应的文件,这也是 Rsync 增量备份的基础之一;

  4. --exclude-from:从文件中读取排除的目录/文件。

    当该文件每行的目录/文件名及其模式被匹配时,对应的文件名将会被忽略。该文件中,每行代表一个模式,可以有 * 号作为通配符,目录后面不用跟着斜杠。

    像这样:

    .git*
    node_modules
    package.*
    .phpactor.json
    *.cache
    
  5. --exclude:与 --exclude-from 一样,都是设定要排除的目录/文件。

    不同的是它不读取文件中的模式,而其值是一个字符串(仅一个模式的时候),或者有多个值,用花括号 {} 包裹着的字符串列表。

    比如: {'file1.txt', 'dir1/*', 'dir2'}

  6. --password-file: 指定在服务器端由参数 secrets file 指定的密码文件中的密码部分(每行的冒号右边部分)作为文件内容的本地文件路径。

    此文件中, 只有一行才是密码,其余行忽略

    密码文件一般赋予 600 权限;

  7. /path/to/htdocs/:表示源目录所在位置,它位于本地计算机上;

    如果路径后面没有斜杠,那么表示将目录 htdocs 上传到服务器的路径中,而不是将目录 htdocs 下的文件(不包括 htdocs 本身)上传到服务器。

    在上文指定 /var/www/wordpress/htdocs 为远程服务器保存文件的路径,
    于是,如果路径后面没有斜杠,上传目录后,站点根目录就在 /var/www/wordpress/htdocs/htdocs 了,这不是作者想要的。

    这就是源目录后面有斜杠与没有斜杠的区别。

    这个问题读者做做实验就明白了。

  8. rsync://wprsync@192.168.1.100:6666/wphtmod/:

    1. rsync://:表示用 rsync 协议;
    2. wprsync:表示服务端在模块中由auto users设置的授权用户名,此用户名不是系统的用户名,只是用来验证登录远程 Rsync 服务的名字;

    3. 192.168.1.100:目标服务器的 IP 地址,也是 Rsync 服务端所在的服务器,指向该 IP 地址的域名也行;

    4. 6666:表示 Rsyncd 接收文件数据的本地网络端口,指定未分配的其他数字也可以;

    5. 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 的使用效果

首次同步

首次同步要把源目录的所有文件都上传到服务器上面:

Rsync正在进行本地到远程的文件传输

首次同步完成

Rsync完成本地到远程的同步

源目录增加文件

首次同步之后,运行同步命令,会将 增加或修改的文件会同步更新到 Rsync 服务器

Rsync的增量备份

删除上述刚刚增加的文件

同步删除文件:

Rsync的差异备份


从服务器同步目标目录和文件到本地

如果服务器端的配置 write only 的值不为 true,则可以执行以下的命令:

rsync -v -a --delete --exclude-from=/path/to/exclude/file.list\
--password-file=/path/to/rsync_passwd \
rsync://wprsync@192.168.1.100:6666/wphtmod/ /path/to/htdocs/

利用 Rsync 从本地复制备份到本地

rsync -av --delete --exclude-from=/path/to/exclude/file.list /path/to/origin /path/to/dest

实际上是把远程目标更换成本地目标就行了。


后记

长篇大论终于到了最后面。

这里就提醒一下,修改完服务器端的配置文件,记得重启一下守护进程,如用到 SystemD,那就使用 systemctl restart rsyncd 命令来重启。

经过上述方式重启后,即使一些配置有错误,也不会影响它重启,更不会显示在 systemctl status -l rsyncd 命令执行后的结果中。

所以,如果要验证重启进程是否成功,可以在客户端尝试执行一次本地到远程的同步命令。

后面作者可能还会继续探索一下 rsync 的参数选项,以及来一篇关于通过 InotifyWait 在 Ubuntu 下进行实时文件的备份和传输。

各位看官,回头见!



程序知路

鉴于本人的相关知识储备以及能力有限,本博客的观点和描述如有错漏或是有考虑不周到的地方还请多多包涵,欢迎互相探讨,一起学习,共同进步。

本文章可以转载,但是需要说明来源出处!

本文使用的部分图片来源于网上,若是侵权,请与本文作者联系删除: admin@icxzl.com