linux服务器之间的文件同步;rsync+inotifywait;同步多个目录

时间:2023-03-09 07:42:20
linux服务器之间的文件同步;rsync+inotifywait;同步多个目录

1、双向同步:unison+inotify

2、单向同步:rsync+inotify

linux服务器之间的文件同步;rsync+inotifywait;同步多个目录

python版的pyinotify

本文介绍第二种方法:

1、Inotify 是一个 Linux特性,它监控文件系统操作,比如读取、写入和创建。Inotify 反应灵敏,用法非常简单,并且比 cron 任务的繁忙轮询高效得多。学习如何将 inotify 集成到您的应用程序中,并发现一组可用来进一步自动化系统治理的命令行工具。inotify是一种强大的,细粒度的,异步文件系统时间监控机制,它可以替代crond实现与rsync的触发式文件同步,从而监控文件系统中添加,删除,修改,移动等细粒事件,从LINUX 2.6.13起,就已加入了对inotify的支持,所以我们只需要安装一个第三方软件inotify-tools即可管理此服务

2、inotify安装:

官网:http://inotify.aiken.cz/?section=inotify&page=download&lang=en

里面就两个C语言的头文件inotify.h和inotify-syscalls.h

linux内核2.6.13以后开始支持这个特性,查看支持情况:[admin@19-56 ~]$ ls -lsart /proc/sys/fs/inotify/

linux服务器之间的文件同步;rsync+inotifywait;同步多个目录

上图表示是支持的

3、inotify-tools安装:其实就是inotify的命令行工具包,这样你就可以通过命令行使用inotify特性

官网:https://github.com/rvoicilas/inotify-tools

https://github.com/rvoicilas/inotify-tools/wiki

inotify-tools is a C library and a set of command-line programs for Linux providing a simple interface to inotify. These programs can be used to monitor and act upon filesystem events.

inotify-tools安装完成之后会有两个命令,inotifywait 和
inotifywatch。inotifywait用于等待文件或者文件集上的一个特定事件,可以监控任何文件或者目录位置,并且可以递归地监控整个目录树;inotifywatch
用于收集被监控的文件系统统计数据,包括每个inotify事件发生多少次等信息。

源码安装:./configure --prefix=/usr && make && su -c 'make install'

yum安装:yum install -y inotify-tools

4、inotifywait -h查看inotifywait的帮助信息,常用选项(options)

-r|--recursive     Watch directories recursively. 递归查询目录

-m|--monitor      Keep listening for events forever.  Without
                         this option, inotifywait will exit after one
                         event is received. 始终监控

-q|--quiet         Print less (only print events). 打印较少信息,仅打印监控相关信息

常用事件(Events):

modify        file or directory contents were written

create        file or directory created within watched directory

delete        file or directory deleted within watched directory

5、rsync -h查看rsync的帮助信息

-v, --verbose               increase verbosity

-a, --archive               archive mode; equals -rlptgoD (no -H,-A,-X)

--delete                delete extraneous files from destination dirs  意思是删除目的目录多余源目录的内容。这样源目录和目的目录的内容才能一致,否则,目的目录的内容不断增加。保持两个目录同步增加和删除

6、重点来了,配置文件

host ip status kernel bit file
A
192.168.10.220
master x86_64 64 /tmp
B
192.168.10.221
slave x86_64 64 /tmp

注意,不要把容易变化又不是监控目标的东西放到监控目录里,这样的话,就不会频繁产生同步操作。更加需要注意的是,不要把下文的日志记录放到监控目录里,这样就产生了死循环:开始同步,产生日志,日志文件发生变化,继续同步,再次产生日志,日志文件再次发生变化,再次同步……

一、主服务器A:

建立密码认证文件

[root@nginx rsync-3.0.9]# cd /usr/local/rsync/
[root@nginx rsync]# echo "rsync-pwd" >/usr/local/rsync/rsync.pwd

其中rsync-pwd可以自己设置密码,rsync.passwd名字也可以自己设置
[root@nginx rsync]# chmod 600 rsync.passwd

无论是为了安全,还是为了避免出现以下错误,密码文件都需要给600权限

创建rsync复制脚本 此项功能主要是将master端的目录/tmp里的内容,如果修改了(无论是添加、修改、删除文件)能够通过inotify监控到,并通过rsync实时的同步给client的/tmp里,下面是通过shell脚本实现的。

#!/bin/bash
host=192.168.10.221 #slave地址
src=/tmp/ #被监控目录
des=web
user=webuser
/usr/local/inotify/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files
do
/usr/bin/rsync -va --delete --progress --password-file=/usr/local/rsync/rsync.passwd $src $user@$host::$des
echo "${files} was rsynced" >>/tmp/rsync.log >&
done

read的用法

如果把rsync.log的放到tmp(备份的目录)就会发送一直复制的问题,所以建议各位吧rsync的日志放到其他的目录下(非备份目录)。
其中host是slave的ip,src是master端要实时监控的目录,des是认证的模块名,需要与slave一致,user是建立密码文件里的认证用户。
把这个脚本命名为rsync.sh,放到监控的目录里,比如我的就放到/tmp下面,并给予764权限

[root@nginx tmp]# chmod 764 rsync.sh

然后运行这个脚本

[root@nginx tmp]# sh /tmp/rsync.sh &

请记住,只有在备份服务器client端的rsync安装并启动rsync之后,在启动rsync.sh脚本,否则有时候会满屏出现:

rsync: failed to connect to 192.168.10.221: Connection refused (111) 
rsync error: error in socket IO (code 10) at clientserver.c(107) [sender=2.6.8]

我们还可以把rsync.sh脚本加入到开机启动项里

[root@nginx tmp]# echo "/tmp/rsync.sh" >> /etc/rc.local

二、备份服务器(slave)

建立用户与密码认证文件

[root@nginx-backup rsync-3.0.9]# echo "webuser:rsync-pwd" > /usr/local/rsync/rsync.passwd

请记住,在master端建立的密码文件,只有密码,没有用户名;而在备份服务端slave里建立的密码文件,用户名与密码都有。

[root@nginx-backup rsync]# chmod 600 rsync.passwd 需要给密码文件600权限

建立rsync配置文件

uid = root
gid = root
use chroot = no
max connections =
strict modes = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsync.lock
log file = /var/log/rsyncd.log
[web]
path = /tmp/ #同步的目的目录
comment = web file
ignore errors
read only = no
write only = no
hosts allow = 192.168.10.220
hosts deny = *
list = false
uid = root
gid = root
auth users = webuser
secrets file = /usr/local/rsync/rsync.pwd

其中web是master服务端里的认证模块名称,需要与主服务器里的一致,以上的配置我的自己服务器里的配置,以供参考。

把配置文件命名为rsync.conf,放到/usr/local/rsync/目录里

启动rsync
[root@nginx-backup rsync]# /usr/local/rsync/bin/rsync --daemon --config=/usr/local/rsync/rsync.conf

我们可以把rsync脚本加入到开机启动项里

[root@nginx-backup rsync]# echo "/usr/local/rsync/bin/rsync --daemon
--config=/usr/local/rsync/rsync.conf" >> /etc/rc.local

现在rsync与inotify在master端安装完成,rsync在备份服务器slave端也安装完成

参考:http://www.showerlee.com/archives/678

http://www.jb51.net/article/57011.htm

20181117更新:

注意点:

1、rsync+inotifywait的同步模式是阻塞模式,一定放到后台执行,不要影响其他任务执行

2、rc.local启动的任务账号都是root账号,所以注意对文件的读写和执行权限

3、启动日志:/var/log/boot.log,可以通过这个日志查看rc.local里的开机启动任务启动情况,是否有异常

4、只可以同步目录和目录下的文件,但是不可以直接同步文件

目的:把服务器A的两个目录的所有变化同步到服务器B

先上服务器配置A

rc.local配置:

#!/bin/sh -x
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
exec 1>/tmp/rc.local.log 2>&1 # send stdout and stderr from rc.local to a log file rc.local的日志默认是在/var/log/boot.log里的,这里把它的日志写到/tmp/rc.local.log中
set -x # tell sh to display commands before execution
touch /var/lock/subsys/local # 作用是确保rc.local不会被执行两次
/bin/sh /usr/local/rsync/rsyncJobs.sh & # 这里一定要加 & 符号,因为这个同步任务是个阻塞的任务,让它在后台执行,这样可以继续执行其他开机启动项
/bin/sh /usr/local/rsync/rsyncNodes.sh & # 上面加了后台执行符号 &,这个任务才会执行

目录一的rsyncJobs.sh配置

#!/bin/bash
host=服务器B的IP
srcJobs=/var/lib/jenkins/jobs/  # 被监控的目录以及递归的目录和文件,但是不可以直接写某个具体的文件
desJobs=jobs  # 目的
user=webuser  # 下面配置的作用是监控目录/var/lib/jenkins/jobs/的任何变化,然后同步到目的地
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $srcJobs \
| while read files
do
sleep 5
rsync -va --delete --progress --password-file=/usr/local/rsync/rsync.pwd $srcJobs $user@$host::$desJobs
echo "${files} was rsynced" >> /tmp/rsyncJobs.log 2>&1  # 把同步文件的简要信息放在这里,大部分相信信息存在/tmp/rc.local.log里
done

目录二的rsyncNodes.sh配置:

#!/bin/bash
host=服务器B的IP
srcNodes=/var/lib/jenkins/nodes/
desNodes=nodes
user=webuser
# inotifwait的作用是监控文件的变化,然后通知rsync进行同步工作
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib $srcNodes \
| while read files
do
sleep 5
rsync -va --delete --progress --password-file=/usr/local/rsync/rsync.pwd $srcNodes $user@$host::$desNodes # --delete删除目标文件比源文件多的文件
echo "${files} was rsynced" >> /tmp/rsyncNodes.log 2>&1
done

密码的rsync.pwd配置:

rsync-pwd  # 只有密码

服务器B配置:

rc.local

#!/bin/sh -x
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.
# 放在rc.local多次执行
touch /var/lock/subsys/local
# 开启rsync服务进程,等待服务器A发起的同步任务
rsync --daemon --config=/usr/local/rsync/rsync.conf

rsync.conf配置

uid=admin  # 决定被同步的文件到服务器A上的用户
gid=admin # 决定被同步的文件到服务器A上的用户组
use chroot=no
max connections=10
strict modes=yes
pid file=/usr/local/rsync/rsyncd.pid # 有的时候启动不了,是因为kill -9后,pid文件还存在。自动生成
lock file=/usr/local/rsync/rsyncd.lock # 有的时候新增加的目录或者修改的配置不生效,是因为这个配置文件没有更新,可以删除下,它会自动生成
log file=/usr/local/rsync/rsyncd.log # 服务器B的rsync服务日志;自动生成
[jobs] # 目录一的配置
path=/var/lib/jenkins/jobs/ # 服务器A的目录一的位置,可以是任意目录,不需要和服务器A的目录保持一致
comment=web file
ignore errors
read only=no
write only=no
hosts allow= 服务器A的IP # 允许连接的IP
hosts deny=*
list=false
uid=admin
gid=admin
auth users=webuser
secrets file=/usr/local/rsync/rsync.pwd
[nodes] # 目录二的配置
path=/var/lib/jenkins/nodes/ # 目录二在服务器B上的位置
comment=web file
ignore errors
read only=no
write only=no
hosts allow=服务器A的IP
hosts deny=*
list=false
uid=admin
gid=admin
auth users=webuser
secrets file=/usr/local/rsync/rsync.pwd

密码的rsync.pwd的配置

webuser:rsync-pwd  # 用户名:密码

启动日志:/var/log/boot.log

rsync -azv --delete --exclude .svn --exclude "compile" --exclude "session_cache" --exclude "web"
/cygdrive/c/www/test/trunk/ username@IP:/home/test/
这里要说的是,同步的时候排除多个文件/文件夹的做法是:
--exclude "文件夹名字(1.唯一的时候,可以直接用文件/文件夹名 2.用绝对路径)"
以下示例,排除3个文件夹:
--exclude .svn --exclude "compile" --exclude "session_cache"
rsync常用参数:

--delete 删除目标文件比源文件多余的文件

--exclude 排除文件(文件不会被同步)

下面使用nload -u M观察到的同步效果图。使用左右方向键可以切换观察的接口

linux服务器之间的文件同步;rsync+inotifywait;同步多个目录