1、双向同步:unison+inotify
2、单向同步:rsync+inotify
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/
上图表示是支持的
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]# 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
如果把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脚本加入到开机启动项里
--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配置
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观察到的同步效果图。使用左右方向键可以切换观察的接口