两台linux主机使用unison + inotify实现web文件夹同步

时间:2021-12-11 06:01:26

两台服务器同步数据

两台linux主机使用unison + inotify实现web文件夹同步

unison 是一款跨平台的文件同步对象,不仅支撑本地对本地同步,也支持通过SSH,RSH和Socket 等网络协议进行同步。

unison 支持双向同步,你可以同A同步到B ,也可以从B同步到A,这些都需要额外的设定。

Inotify一种强大的、细粒度的、异步文件系统监控机制,它满足各种各样的文件监控需要,可以监控文件系统的访问属性、读写属性、权限属性、删除创建、移动等操作,也就是可以监控文件发生的一切变化。

inotify-tools是一个C库和一组命令行的工作提供Linux下inotify的简单接口。

inotify-tools安装后会得到inotifywaitinotifywatch这两条命令:

  • inotifywait命令可以用来收集有关文件访问信息,Linux发行版一般没有包括这个命令,需要安装inotify-tools,这个命令还需要将inotify支持编译入Linux内核,好在大多数Linux发行版都在内核中启用了inotify。
  • inotifywatch命令用于收集关于被监视的文件系统的统计数据,包括每个 inotify 事件发生多少次。

开始之前需要检测系统内核是否支持inotify:

使用uname -r命令检查Linux内核,如果低于2.6.13,就需要重新编译内核加入inotify的支持。

使用ll /proc/sys/fs/inotify命令,是否有以下三条信息输出,如果没有表示不支持

 

/web1> ll /proc/sys/fs/inotify
总计 0
-rw-r--r-- 1 root root 0 07-26 12:44 max_queued_events
-rw-r--r-- 1 root root 0 07-26 12:44 max_user_instances
-rw-r--r-- 1 root root 0 07-26 12:44 max_user_watches

安装篇

下载ocaml组件并安装:

wget http://caml.inria.fr/pub/distrib/ocaml-4.02/ocaml-4.02.1.tar.gz

  

下载unison :

wget http://www.seas.upenn.edu/~bcpierce/unison//download/releases/beta/unison-2.48.1.tar.gz

  

下载inotify:

wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz

  

两台服务器都编译安装这三个源码包,在此只写在一台服务器上的编译安装的过程

安装ocaml组件:

tar zxvf ocaml-4.02.1.tar.gz;
cd ocaml-4.02.1;
./configure;
make world opt
make install

 安装inotify:

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

[root@localhost inotify-tools-3.14]# cd /usr/local/inotify/

##修改PATH 环境变量:
[root@localhost inotify]# echo "PATH=/usr/local/inotify/bin:$PATH" > /etc/profile.d/inotify.sh
[root@localhost inotify]# source /etc/profile.d/inotify.sh
##添加库文件到系统识别的路径: [root@localhost inotify]# echo "/usr/local/inotify/lib" > /etc/ld.so.conf.d/inotify.conf [root@localhost inotify]# ldconfig -v | grep inotify /usr/local/inotify/lib: libinotifytools.so.0 -> libinotifytools.so.0.4.1 ##链接库文件到系统识别的路径: [root@localhost inotify]# ln -sv /usr/local/inotify/include/ /usr/include/inotify `/usr/include/inotify' -> `/usr/local/inotify/include/'

 安装unison程序:

[root@localhost ocam]# cd /usr/src/unison/

[root@localhost unison]# yum -y install ctags-etags

[root@localhost unison]# make UISTYLE=text

[root@localhost unison]# make install

mv /root/bin//unison /tmp/unison-29781

mv: 无法获取"/root/bin//unison" 的文件状态(stat): 没有那个文件或目录

make: [doinstall] 错误 1 (忽略)

cp unison /root/bin/

cp: 无法创建普通文件"/root/bin/": 是一个目录

make: *** [doinstall] 错误 1

报错信息,依据提示操作:此错误就是要把unison 复制到/usr/local/bin下
cp /usr/src/unison/unison /usr/local/bin/
mkdir -p /root/bin/ //在次执行 make install
mv /root/bin//unison /tmp/unison-29807
cp unison /root/bin/
cp unison /root/bin/unison

在服务器B 上的安装同上。 

配置服务器A和B ssh互信关系

# ssh-keygen -t rsa
[root@localhost ~]# scp ~/ .ssh/id_rsa.pub 10.1.204.16:/root/ ##在服务器B 上移动公钥并重命名 [root@localhost ~]# mv id_rsa.pub ./.ssh/authorized_keys ##公钥授权为600 [root@localhost ~]# chmod 600 .ssh/authorized_keys ## 服务器B 重启sshd服务 [root@localhost ~]# service sshd restart

测试两台服务器免密钥登陆

## 服务器A 登陆服务器B
[root@localhost ~]# ssh root@10.1.204.16
Last login: Wed Nov 29 13:47:07 2017 from 10.1.204.15
[root@localhost ~]# exit
logout
Connection to 10.1.204.16 closed.

编辑unison 同步的脚本进行测试  

A服务器(A-B):

#!/bin/bash

ipB="10.1.204.16"
srcA="/home/x/web1/"
dstB="/home/x/web1/"
/usr/local/inotify/bin/inotifywait -mrq -e create,delete,modify,move $srcA | while read line; do /usr/local/bin/unison -batch $srcA ssh://$ipB//$dstB echo -n "$line " >> /var/log/inotify.log echo `date | cut -d " " -f1-4` >> /var/log/inotify.log done

  

 

B服务器(B-A):

ipA="10.1.204.15"

srcB="/home/x/web1"

dstA="/home/x/web1"

/usr/local/inotify/bin/inotifywait -mrq -e create,delete,modify,move $srcB | while read line; do

/usr/local/bin/unison -batch $srcB ssh://$ipA/$dstA

echo -n "$line " >> /var/log/inotify.log

echo `date | cut -d " " -f1-4` >> /var/log/inotify.log

done

测试webA webB 上传代码同步

A-B

启动webA脚本
[root@localhost scripts]# sh -x serA.sh 在webA上在开个终端,创建{1-5}.txt [root@localhost web1]# touch {1..5}.txt 在webB上查看:目标文件都已经同步过来 [root@localhost web1]# ls 1.txt 2.txt 3.txt 4.txt 5.txt

B-A

a .启动webB上的脚本

[root@localhost scripts]# sh -x serB.sh
在webB上创建{a..e}.txt, 在web1上查看 [root@localhost web1]# touch {a..e}.txt
[root@localhost web1]# ls 1.txt 2.txt 3.txt 4.txt 5.txt a.txt b.txt c.txt d.txt e.txt 在webA上查看: 目标文件都已同步过来 [root@localhost web1]# ls 1.txt 2.txt 3.txt 4.txt 5.txt a.txt b.txt c.txt d.txt e.txt

  

模式匹配:

unison 工具支持排除指定目录功能,比如排除log目录和.log文件

如下参数 ignore/ignorenot, follow, sortfirst/sortlast, backup, merge 定义各自的匹配模式。 例如: ignore = pattern pattern 的语法格式

● Regex regexp 即常规表达式。

● Name name   路径的最后一部分与 “name" 匹配。可以使用通配符,见下面描述。

● Path path 全路径与 "path" 匹配。可以使用通配符,见下面描述。

以下通配符可以用在 Path 和 Name 中:

● ? 匹配除了 "/" 之外,任意单个字符;

● * 匹配除了 "/" 之外的任意字符;如果用在 "Name" 中,则不和以 "."开始的文件匹配,而用在 "Path" 中,可以和 "." 开始的向匹配。

● [xyz] 匹配 {x,y,z} 中任一字符;

● {a,bb,ccc} 匹配 a, bb, ccc 中任何一个;

示例:

● 忽略 CVS 目录以及以 .cmo 结尾的文件: ignore = Name {CVS,*.cmo}

● 忽略路径 a/b: ignore = Path a/b

● 忽略路径 */tmp。当 * 用在 Path 中,可以和以 "." 开始的文件、目录名匹配,如下面的和 ".foo/tmp" 匹配; ignore = Path */tmp

● 忽略 a/b/ 开始,结尾是 .ml 的文件。 ignore = Regex a/b/.*\.ml

生产环境要求忽略log目录和.log文件

在webA  webB 中 添加:
[root@localhost scripts]# vim /root/.unison/default.prf

ignore=Name {log,*.log}

启动webA webB 脚本
[root@localhost scripts]# sh -x serA.sh
[root@localhost scripts]# sh -x serB.sh
webA上创建log 日志文件

[root@localhost web1]# touch x.log

webB上查询:  x.log 日志文件没有同步过来,验证成功

[root@localhost web1]ls

  

webA 上脚本后台启动并添加到开机启动
[root@localhost scripts]# chmod +x serA.sh
[root@localhost scripts]# ll
总用量 8
-rwxr-xr-x. 1 root root 406 11月 30 13:48 serA.sh
[root@localhost scripts]# nohup ./serA.sh &
[root@localhost scripts]# echo "/root/scripts/serA.sh" >> /etc/rc.local
[root@localhost scripts]# cat /etc/rc.local
#!/bin/sh
#
# 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. touch /var/lock/subsys/local
/root/scripts/serA.sh

  

附录:

inotifywait命令使用

path=$1
/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y/%H:%M' --format '%T %w %f' -e modify,delete,create,attrib $path

inotifywait命令参数

  • -m是要持续监视变化。
  • -r使用递归形式监视目录。
  • -q减少冗余信息,只打印出需要的信息。
  • -e指定要监视的事件列表。
  • --timefmt是指定时间的输出格式。
  • --format指定文件变化的详细信息。 

可监听的事件

事件 描述
access 访问,读取文件。
modify 修改,文件内容被修改。
attrib 属性,文件元数据被修改。
move 移动,对文件进行移动操作。
create 创建,生成新文件
open 打开,对文件进行打开操作。
close 关闭,对文件进行关闭操作。
delete 删除,文件被删除。

 

  

/root/.unison/default.prf配置参数

# Unison preferences file

root = /tmp/www.91town.xxx #本地文件夹

root = ssh://root@192.168.0.230//tmp/www.91town.xxx #远程文件夹

batch = true #表示全自动模式,接受并执行默认动作。

owner = true #表示保持同步的文件属主信息。

group = true #表示保持同步的文件属组信息。

perms = -1 #表示保持同步的文件读写权限。

#fastcheck = false

fastcheck = true #true表示同步时通过文件的创建时间来比较两地文件;false表示同步时通过比较两地文件内容。

rsync = false #默认值是true,用于激活rsync传输模式。

sshargs = -C #使用ssh的压缩传输方式。

xferbycopying = true #优化传输参数,默认值为true。

confirmbigdel = false #默认值为true,表示当需要同步的两个目录有一个为空时,unison将停止。设置为false可以保证当需要同步的某个目录为空时,unison不会停止运转。

log = true #表示在终端输出运行信息。

logfile = /var/log/unison.log #指定同时输出写入log文件。

maxthreads = 300 #指定同步时最大线程数。

#repeat = 1 #表示间隔1秒后开始一次新的同步检查

#retry = 3 #指定失败重试次数

#path = www

#同步指定的子目录及文件,而非整个目录。可以写多个path,如在下面再写一个path = wwwbak。

#ignore = Path WEB-INF/tmp

#忽略/wwwroot下面的WEB-INF/tmp目录,即同步时不同步它。注意,这里是”Path”,而不是”path”。

force表示会以本地所指定文件夹为标准,将该目录同步到远端。这里需要注意,如果指定了force参数,那么Unison就变成了单项同步了,也就是说会以force指定的文件夹为准进行同步,类似与rsync
force和prefer需要一起配置 -ignore xxx //增加 xxx 到忽略列表中
-ignorecase [true|false|default] //是否忽略文件名大小写
-follow xxx //是否支持对符号连接指向内容的同步
owner = true //保持同步过来的文件属主
group = true //保持同步过来的文件组信息
perms = -1 //保持同步过来的文件读写权限
repeat = 1 //间隔1秒后,开始新的一次同步检查
retry = 3 //失败重试
sshargs = -C //使用ssh的压缩传输方式
xferbycopying = true"
-immutable xxx //不变目录,扫描时可以忽略
-silent //安静模式
-times //同步修改时间
-path xxx 参数 //只同步 -path 参数指定的子目录以及文件,而非整个目录,-path 可以多次出现。 PS:Windows下的unison配置文件默认位于C:\Documents and Settings\currentuser\.unison目录,默认的配置文件名是default.prf。

  

 举例:

# Unison preferences file
ignore=Name {log,*.log}
batch=true
force=/home/x/web1/
prefer = ssh://10.1.208.16///home/x/web1/
maxthreads=300
repeat = 60
retry = 3
owner = true
group = true
perms = -1
sshargs = -C
log = true
logfile = /home/x/unison.log