Linux平台上文件同步——rsync+inotify之实时同步

1 前言

1.1 概述

本文介绍使用rsync和 inotify-tools,实现linux 上的本地实时同步和本地定时同步的方法。

1.2 实验环境

服务器两台
操作系统: CentOS-7.4

软件:
rsync.x86_64 3.0.9-18.el7
inotify-tools.x86_64 3.14-9.el7
xinetd.x86_64 2:2.3.15-13.el7

本地同步环境信息:
源目录: /root/data/
目的目录:/root/backup/

远程同步环境信息:
源主机(即原始文件所在的服务器)的ip地址:10.40.239.234
目标主机(存放备份文件的服务器)的ip地址:10.40.239.236
源目录: /root/data/
目的目录:/root/backup/

1.3 软件介绍

1.3.1 rsync

rsync是linux系统下的数据镜像备份工具。使用快速增量备份工具Remote Sync可以远程同步,支持本地复制,或者与其他SSH、rsync主机同步。
它有如下特性:

  1. 可以镜像保存整个目录树和文件系统。
  2. 可以很容易做到保持原来文件的权限、时间、软硬链接等等。
  3. 无须特殊权限即可安装。
  4. 快速:第一次同步时 rsync 会复制全部内容,但在下一次只传输修改过的文件。rsync 在传输数据的过程中可以实行压缩及解压缩操作,因此可以使用更少的带宽。
  5. 安全:可以使用scp、ssh等方式来传输文件,当然也可以通过直接的socket连接。
    支持匿名传输,以方便进行网站镜像。

1.3.2 inotify-tools

inotify-tools 是为linux下inotify文件监控工具提供的一套c的开发接口库函数,同时还提供了一系列的命令行工具,这些工具可以用来监控文件系统的事件。 inotify-tools是用c编写的,除了要求内核支持inotify外,不依赖于其他。inotify-tools提供两种工具,一是inotifywait,它是用来监控文件或目录的变化,二是inotifywatch,它是用来统计文件系统访问的次数。

2 实时同步

实时同步是使用 rsync和inotify-tools来完成的。实时同步方式中,服务器主动将文件差异部分发送给客户端。

2.1 本地实时同步

  1. 下载并安装inotify-tools,有两种方法:
    (1) 在https://sourceforge.net/projects/inotify-tools/ 下载inotify。
    解压下载后的文件,本文中使用的是inotify-tools-3.14.tar.gz。

tar -zxvf inotify-tools-3.14.tar.gz

   进入解压后的目录,编译和安装inotify-tools:

cd inotify-tools-3.14
./configure --prefix=/usr/local/inotify make &&
make install

(2) 使用yum 安装。

yum –y inotify-tools

查看 inotify 的安装位置是 /usr/local/inotify。两个命令inotifywait 和 inotifywatch位于 目录 /usr/local/inotify/bin/ 中。

  1. 安装 rsync

yum install rsync

  1. 配置 rsync 参数文件 /etc/rsyncd.conf,内容如下:

    # /etc/rsyncd: configuration file for rsync daemon mode
    # See rsyncd.conf man page for more options.
    # configuration example:

    uid = nobody
    gid = nobody
    use chroot = no
    max connections = 200
    timeout = 300
    pid file = /var/run/rsyncd.pid
    lock file = /var/run/rsync.lock
    log file = /var/log/rsyncd.log
    read only = false
    list = false
    dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

  2. 启动 rsync:

systemctl start rsync

  1. 修改inotify默认参数(inotify默认内核参数值太小)
    查看系统默认参数值:

sysctl -a | grep max_queued_events

结果是:fs.inotify.max_queued_events = 16384

sysctl -a | grep max_user_watches

结果是:fs.epoll.max_user_watches = 378327

sysctl -a | grep max_user_instances

结果是:fs.inotify.max_user_instances = 128

修改参数:

sysctl -w fs.inotify.max_queued_events=“99999999” sysctl -w
fs.inotify.max_user_watches=“99999999” sysctl -w
fs.inotify.max_user_instances=“65535”

参数说明:
max_queued_events:
inotify队列最大长度,如果值太小,会出现"** Event Queue Overflow **"错误,导致监控文件不准确
max_user_watches:
要同步的文件包含多少目录,可以用:find /Data/xqsj_upload -type d | wc -l 统计这些源目录下的目录数,必须保证max_user_watches值大于统计结果(这里/Data/xqsj_upload为同步的源文件目录)
max_user_instances:
每个用户创建inotify实例最大值。

  1. 创建实时同步脚本rsync_inotify.sh,内容如下:
#!/bin/bash
src_dir=/root/data
dest_dir=/root/backup
/usr/local/inotify/bin/inotifywait -mrq --timefmt ' '%Y/%m/%d %H:%M:%S' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $src_dir | while read file
do
/usr/bin/rsync -avz --port=873 --progress --delete $src_dir $dest_dir
echo " ${file} was rsynced" >> /tmp/rsync.log 2>&1
done

本实验中,这个文件的路径是/root/rsync_inotify.sh

chmod 744 rsync_inotify.sh

  1. 在后台运行这个脚本:

./rsync_inotify.sh

  1. 将脚本的执行添加到开机启动项中。

echo ‘sh /root/rsync_inotify.sh &’ >>/etc/rc.local

这样就实现了本地的实时同步。
查看后台运行的作业:

jobs

 结果如下:

[1]+ Running ./test.sh &

可以看到,它的作业号为1

如果想结束这个作业,可以执行:

fig %1

其中1表示作业号。

2.2 远程实时同步

2.2.1 shell模式

  1. 需要在目标主机和服务器端都安装rsync:
    使用 yum 安装rsync

yum install rsync

  1. 在源主机配置 rsync 参数文件 /etc/rsyncd.conf,内容如下:

# /etc/rsyncd: configuration file for rsync daemon mode
# See rsyncd.conf man page for more options.
# configuration example:

pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
logfile = /var/log/rsyncd.log
uid = nobody
gid = nobody
use chroot = no
max connections = 200
timeout = 300
port = 873
read only =false
list = false
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2

  1. 在源主机和目标主机重启 rsync:

systemctl restart rsync

  1. 如果要求源主机主动将文件的差异部分发送给目标主机, 那么源主机需要免密连接到目标主机。所以要在源主机生成公钥和私钥,命令如下:

ssh-keygen -t rsa

输入命令后只需要一直点击enter键即可,直到出现如图界面,那么它提示你公钥和私钥保存在哪个位置。

打开公钥文件/root/.ssh/id_rsa,复制它的内容。

  1. 在目标主机中,进入目录 /root/.ssh,编辑文件 authorized_keys,将源主机公钥的内容粘贴到文件末尾。

  2. 在目标主机重启ssh:

systemctl restart sshd

  1. 在源主机验证能否免密登录

ssh [email protected]

如果出现如下的提示信息,表示免密登录成功:

  1. 完成免密认证的配置后,在源主机上安装inotify-tools。

yum –y inotify-tools

查看 inotify 的安装位置是 /usr/local/inotify。两个命令inotifywait 和 inotifywatch位于 目录 /usr/local/inotify/bin/ 中

  1. 修改inotify默认参数(inotify默认内核参数值太小)
    查看系统默认参数值:

sysctl -a | grep max_queued_events

结果是:fs.inotify.max_queued_events = 16384

sysctl -a | grep max_user_watches

结果是:fs.epoll.max_user_watches = 378327

sysctl -a | grep max_user_instances

结果是:fs.inotify.max_user_instances = 128

修改参数:

sysctl -w fs.inotify.max_queued_events=“99999999” sysctl -w
fs.inotify.max_user_watches=“99999999” sysctl -w
fs.inotify.max_user_instances=“65535”

参数说明:
max_queued_events:
inotify队列最大长度,如果值太小,会出现"** Event Queue Overflow **"错误,导致监控文件不准确
max_user_watches:
要同步的文件包含多少目录,可以用:find /Data/xqsj_upload -type d | wc -l 统计这些源目录下的目录数,必须保证max_user_watches值大于统计结果(这里/Data/xqsj_upload为同步的源文件目录)
max_user_instances:
每个用户创建inotify实例最大值。

  1. 在源主机上创建定时同步脚本rsync_inotify.sh,内容如下:
#!/bin/bash
src_dir=/root/data/
remote_addr=10.40.239.236
dest_dir=/root/backup/
user=rsync_user
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%Y/%m/%d %H:%M:%S' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $src_dir | while read file
do
    /usr/bin/rsync -avz  --delete $src_dir $user@$remote_addr:$dest_dir --password-file=/etc/rsync.pass
    echo " ${file} was rsynced" >> . /rsync.log 2>&1
done

本文这个文件的路径是/root/rsync_inotify.sh,修改它的权限使用:

chmod 744 rsync_inotify.sh

  1. 在后台运行这个脚本:

./rsync_inotify.sh

  1. 将脚本的执行添加到开机启动项中。

echo ‘sh /root/rsync_inotify.sh &’ >>/etc/rc.local

2.2.2 后台进程模式

  1. 在源主机和目标主机都安装 rsync 和 xinetd:

yum install rsync
yum install xinetd

  1. 在目标主机新建或编辑 /etc/rsyncd.conf,配置rsync相关参数:

# /etc/rsyncd: configuration file for rsync daemon mode
# See rsyncd.conf man page for more options.
# configuration example:

pid file = /var/run/rsyncd.pid lock
file = /var/run/rsync.lock log
file = /var/log/rsyncd.log

[backup]
path = /root/backup/
comment = backup
uid = root
gid = root
use chroot = no
max connections = 200
timeout = 300
port = 873
read only = false
list = false
dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2
hosts allow = 10.40.239.234/24
secrets file = /etc/rsync.pass
auth users = rsync_user

注意:这种方法需要在 /etc/rsyncd.conf 中 将 uid,gid配置为目标主机中备份目录的所属用户和用户组,不能配置为nobody和其他用户。

  1. 在目标主机创建密码文件:

vi /etc/rsync.pass

写入源主机用户的用户名和密码,格式是用户:密码

rsync_user:!QAZ2wsx

  1. 设置文件权限,即rsync.pass认证文件是600权限!

chmod 600 /etc/rsync.pass

  1. 在目标主机上重启rsync

systemctl restart rsyncd

  1. 在目标主机上新建或编辑 /etc/xinetd.d/rsync,配置rsync相关参数:

# default: off # description: The rsync server is a good addition
to an ftp server, as it \ # allows crc checksumming etc.
service rsync {
disable = no #由默认的yes改为no,设置开机启动rsync
socket_type = stream
wait = no
user = root
server = /usr/bin/rsync
server_args = --daemon
log_on_failure += USERID
}

  1. 重新启动xinetd:

systemctl restart xinetd

  1. 在源主机,创建一个密码文件,内容只有密码,和源主机的密码文件中的密码相同。这里,我设置的密码文件的位置是 /etc/rsync.pass,内容是 !QAZ2wsx。并修改其权限:

chmod 600 /etc/rsync.pass

  1. 在目标主机和源主机关闭防火墙和selinux,这是必要的。

systemctl stop firewalld
setenforce 0

  1. 在源主机上安装inotify-tools:

yum –y inotify-tools

查看 inotify 的安装位置是 /usr/local/inotify。两个命令inotifywait 和 inotifywatch位于 目录 /usr/local/inotify/bin/ 中

  1. 修改inotify默认参数(inotify默认内核参数值太小)
    查看系统默认参数值:

sysctl -a | grep max_queued_events

结果是: fs.inotify.max_queued_events = 16384

sysctl -a | grep max_user_watches

结果是: fs.epoll.max_user_watches = 378327

sysctl -a | grep max_user_instances

结果是: fs.inotify.max_user_instances = 128

修改参数:

sysctl -w fs.inotify.max_queued_events=“99999999” sysctl -w
fs.inotify.max_user_watches=“99999999” sysctl -w
fs.inotify.max_user_instances=“65535”

参数说明:
max_queued_events:
inotify队列最大长度,如果值太小,会出现"** Event Queue Overflow **"错误,导致监控文件不准确
max_user_watches:
要同步的文件包含多少目录,可以用:find /Data/xqsj_upload -type d | wc -l 统计这些源目录下的目录数,必须保证max_user_watches值大于统计结果(这里/Data/xqsj_upload为同步的源文件目录)
max_user_instances:
每个用户创建inotify实例最大值。

  1. 在源主机上创建定时同步脚本rsync_inotify.sh,内容如下:
#!/bin/bash
src_dir=/root/data/
remote_addr=10.40.239.236
user=rsync_user
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%Y/%m/%d %H:%M:%S' --format '%T %w%f%e' -e close_write,modify,delete,create,attrib,move $src_dir | while read file
do
/usr/bin/rsync -avz --port=873 --delete $src_dir $user@$remote_addr::backup --password-file=/etc/rsync.pass
echo " ${file} was rsynced" >> . /rsync.log 2>&1
done

本文这个文件的路径是/root/rsync_inotify.sh,修改它的权限

chmod 744 rsync_inotify.sh

  1. 在后台运行这个脚本:

./rsync_inotify.sh

  1. 将脚本的执行添加到开机启动项中。

echo ‘sh /root/rsync_inotify.sh &’ >>/etc/rc.local

参考

[1] rsync. rsyncd.conf.2018-01-28
[2]百度百科. rsync
[3] 十五十六. rsync搭建部署和配置文件详解. 2018-05-29
[4] wc1695040842. rsync+inotify实时同步文件. 2019-06-03
[5] 王晓冬. Rsync故障排查整理. 2017-03-14

附:Rsyncd.conf 配置参数

模块参数
主要是定义服务器哪个目录要被同步。其格式必须为“[module]”形式,这个名字就是在rsync 客户端看到的名字,其实有点象Samba服务器提供的共享名。而服务器真正同步的数据是通过 path 来指定的。我们可以根据自己的需要,来指定多个模块,模块中可以定义以下参数:
comment
给模块指定一个描述,该描述连同模块名在客户连接得到模块列表时显示给客户。默认没有描述定义。

path
指定该模块的供备份的目录树路径,该参数是必须指定的。

use chroot
如果" use chroot" 指定为true,那么rsync在传输文件以前首先chroot到path参数所指定的目录下。这样做的原因是实现额外的安全防护,但是缺点是需要以roots权限,并且不能备份指向外部的符号连接所指向的目录文件。默认情况下chroot值为true。

uid
该选项指定当该模块传输文件时,守护进程应该具有的uid,配合gid选项使用可以确定哪些可以访问怎么样的文件权限,默认值是" nobody" 。

gid
该选项指定当该模块传输文件时,守护进程应该具有的gid。默认值为" nobody" 。

max connections
指定该模块的最大并发连接数量以保护服务器,超过限制的连接请求将被告知随后再试。默认值是0,也就是没有限制。

list
该选项设定当客户请求可以使用的模块列表时,该模块是否应该被列出。如果设置该选项为false,可以创建隐藏的模块。默认值是true。

read only
该选项设定是否允许客户上载文件。如果为true那么任何上载请求都会失败,如果为false并且服务器目录读写权限允许那么上载是允许的。默认值为true。

exclude
用来指定多个由空格隔开的多个文件或目录(相对路径),并将其添加到exclude列表中。这等同于在客户端命令中使用–exclude来指定模式,一个模块只能指定一个exclude选项。但是需要注意的一点是该选项有一定的安全性问题,客户很有可能绕过exclude列表,如果希望确保特定的文件不能被访问,那就最好结合uid/gid选项一起使用。

exclude from
指定一个包含exclude模式的定义的文件名,服务器从该文件中读取exclude列表定义。

include
用来指定不排除符合要求的文件或目录。这等同于在客户端命令中使用–include来指定模式,结合include和exclude可以定义复杂的exclude/include规则。

include from
指定一个包含include模式的定义的文件名,服务器从该文件中读取include列表定义。

auth users
该选项指定由空格或逗号分隔的用户名列表,只有这些用户才允许连接该模块。这里的用户和系统用户没有任何关系。如果" auth users" 被设置,那么客户端发出对该模块的连接请求以后会被rsync请求challenged进行验证身份这里使用的challenge/response认证协议。用户的名和密码以明文方式存放在" secrets file" 选项指定的文件中。默认情况下无需密码就可以连接模块(也就是匿名方式)。

secrets file
该选项指定一个包含定义用户名:密码对的文件。只有在" auth users" 被定义时,该文件才有作用。文件每行包含一个username:passwd对。一般来说密码最好不要超过8个字符。没有默认的secures file名,需要限式指定一个(例如:/etc/rsyncd.passwd)。注意:该文件的权限一定要是600,否则客户端将不能连接服务器。

strict modes
该选项指定是否监测密码文件的权限,如果该选项值为true那么密码文件只能被rsync服务器运行身份的用户访问,其他任何用户不可以访问该文件。默认值为true。

hosts allow
该选项指定哪些IP的客户允许连接该模块。客户模式定义可以是以下形式:
单个IP地址,例如:192.167.0.1

整个网段,例如:192.168.0.0/24,也可以是192.168.0.0/255.255.255.0
多个IP或网段需要用空格隔开,“*”则表示所有,默认是允许所有主机连接。

hosts deny
指定不允许连接rsync服务器的机器,可以使用hosts allow的定义方式来进行定义。默认是没有hosts deny定义。

ignore errors
指定rsyncd在判断是否运行传输时的删除操作时忽略server上的IO错误,一般来说rsync在出现IO错误时将将跳过–delete操作,以防止因为暂时的资源不足或其它IO错误导致的严重问题。

ignore nonreadable
指定rysnc服务器完全忽略那些用户没有访问权限的文件。这对于在需要备份的目录中有些文件是不应该被备份者得到的情况是有意义的。

lock file
指定支持max connections参数的锁文件,默认值是/var/run/rsyncd.lock。

transfer logging
使rsync服务器使用ftp格式的文件来记录下载和上载操作在自己单独的日志中。

log format
通过该选项用户在使用transfer logging可以自己定制日志文件的字段。其格式是一个包含格式定义符的字符串,可以使用的格式定义符如下所示:
%h 远程主机名
%a 远程IP地址
%l 文件长度字符数
%p 该次rsync会话的进程id
%o 操作类型:" send" 或" recv"
%f 文件名
%P 模块路径
%m 模块名
%t 当前时间
%u 认证的用户名(匿名时是null)
%b 实际传输的字节数
%c 当发送文件时,该字段记录该文件的校验码
默认log格式为:" %o %h [%a] %m (%u) %f %l" ,一般来说,在每行的头上会添加" %t [%p] " 。在源代码中同时发布有一个叫rsyncstats的perl脚本程序来统计这种格式的日志文件。

timeout
通过该选项可以覆盖客户指定的IP超时时间。通过该选项可以确保rsync服务器不会永远等待一个崩溃的客户端。超时单位为秒钟,0表示没有超时定义,这也是默认值。对于匿名rsync服务器来说,一个理想的数字是600。

refuse options
通过该选项可以定义一些不允许客户对该模块使用的命令参数列表。这里必须使用命令全名,而不能是简称。但发生拒绝某个命令的情况时服务器将报告错误信息然后退出。如果要防止使用压缩,应该是:" dont compress = *" 。

dont compress
用来指定那些不进行压缩处理再传输的文件,默认值是*.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz

猜你喜欢

转载自blog.csdn.net/international24/article/details/105136093