Unison+inotify-tools实现Centos主机间的多机触发式双向同步

概述

 

 

最近在做一个web项目,要求做成群集形式。方案是nginx+tomcat+memcached_session_manager,部署环境是Centos6.5。项目快完成时发现自己忽略了文件同步问题,于是立即开动google,满世界寻找解决方案。

 

这个项目有很多需要用户上传的文件,比如用户的形象照片,视频文件等。在群集中,用户上传的文件往往被某个节点的服务器保存在该物理服务器的某个目录下。那么其它节点的服务器如何访问这些文件呢?一般来说,有两种解决方案,一是NFS,即设立专门的网络文件服务器;二是同步远程服务器的文件目录,使其保持一致。

 

NFS方案比较简单,但访问速度会相对比较慢,而且所有的文件通过网络来存取,个人感觉效率太低下。另外,为了保证单台NFS失效时网站的正常运行,我们还需要将NFS配置成多台群集的模式,增加了成本和复杂性。

 

第二种方案可以很好地兼顾成本和效率,是可以接受的方式。但笔者以前没有在Ubuntu上实现过远程文件同步的经验,因此查找资料和摸索配置,寻找最优方案的工作整整进行了两天。郁闷啊!

 

 

 

最后选定的方案如下:

 

Unison:               实现双向同步

 

Inotify tools:              监控文件系统

 

OpenSSH:           远程主机间的文件传输

 

软件介绍

 

OpenSSH

 

OpenSSH 是 SSH (Secure SHell) 协议的免费开源实现。

 

它用安全、加密的网络连接工具代替了 telnet、ftp、 rlogin、rsh 和 rcp 工具。OpenSSH 支持 SSH 协议的版本 1.3、1.5、和 2。自从 OpenSSH 的版本2.9以来,默认的协议是版本2,该协议默认使用 RSA 钥匙。

 

OpenSSH的项目地址如下:http://www.openssh.com/

 

 

 

Unison

 

Unison是一款跨平台的文件同步工具,不仅支持本地对本地同步,也支持通过SSH、RSH和Socket等网络协议进行同步。更棒的是,Unison支持双向同步操作,你既可以从A同步到B,也可以从B同步到A,这些都不需要额外的设定。

 

Unison的项目地址:http://www.cis.upenn.edu/~bcpierce/unison/

 

 

 

Inotify tools

 

Inotify是一种文件变化通知机制,Linux内核从2.6.13开始引入。在BSD和Mac OS系统中比较有名的是kqueue,它可以高效地实时跟踪Linux文件系统的变化。近些年来,以fsnotify作为后端,几乎所有的主流Linux发行版都支持Inotify机制。

 

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

 

Inotify-tools的项目地址:http://sourceforge.net/projects/inotify-tools/

 

 

 

软件安装

 

准备工作

 

安装操作系统Centos6.5,32位或者64位。假设我们有3台安装了Centos6.5的Web服务器,分别为:

 

server1           192.168.0.101

 

server2           192.168.0.102

 

server3           192.168.0.103

 

server4           192.168.0.104

 

其默认用户名分别为user1、user2、user3、user4。

 

 

 

需要同步的目录均为:/var/www/html

 

安装OpenSSH

 

在各台服务器上安装OpenSSH,使用如下命令:

 

yum  install openssh  -y

 

该命令在你的机器上同时安装了SSH Server和SSH Client。

 

安装Unison

 

在各个需要同步的服务器上执行以下命令安装unison:

 

yum  install unison  -y

 

安装Inotify tools

 

在各个需要同步的服务器上执行以下命令安装inotify-tools:

 

yum install inotify-tools  -y

 

 

 

配置

 

多机同步的拓扑结构

 

在web群集中,同步在多机之间进行,而unison的同步功能仅支持双机。因此我们设计了一个星型的拓扑结构,来实现多机的同步。其设计思想就是利用unison的双向同步功能,指定一台服务器为星型结构的主服务器(server1),剩余服务器与其进行双向同步。这样,任何一台服务器上的文件变化都可以通过这个结构扩散,从而达到多机同步的目的。

这一结构的缺点是一旦server1当机失效,同步就会失败。因此,有必要的话,可以组成双主服务器的星型结构来弥补。

配置双机信任(ssh key)

 

Unison通过SSH来进行文件同步时,需要用户手工输入远程主机的登录密码。而我们试图通过开机自启动的脚本来实现自动的同步功能。因此,我们需要为SSH配置双机信任,使双方在使用ssh时不需要再输入密码。

 

使用 ssh-keygen和ssh-copy-id配置一下就可以无需输入密码直接登录服务器了。

ssh-keygen 创建公钥和密钥。
ssh-copy-id 把本地主机的公钥复制到远程主机的authorized_keys文件上。
ssh-copy-id 也会给远程主机的用户主目录(home)和~/.ssh, 和~/.ssh/authorized_keys设置合适的权限

生成秘钥对

 

在server2、server3、server4上分别生成一对公钥/私钥:

 

 

Python代码
  1. ssh-keygen -t rsa

 

 

 

命令执行完毕后,密钥对就生成了,公钥是~/.ssh/id_rsa.pub,私钥是~/.ssh/id_rsa。

 

将公钥复制到服务器

 

在server2、server3、server4上分别使用OpenSSH的ssh-copy-id工具将公钥写入server1上的~/.ssh/authorized_keys。命令如下:

 

 

Python代码
  1. ssh-copy-id -i .ssh/id_rsa.pub root@192.168.0.101

 

 

 

反向配置

 

在server1上按照上述方法生成秘钥对,然后将公钥分别复制到server2、server3、Server4。

 

SSH登录测试

 

在server2上用SSH登录到server1上测试一下:

 

ssh user1@192.168.0.101

 

如果系统不再提示你输入密码而直接登录到了server1,说明我们的配置成功了。

 

 

 

创建.sh脚本来实现同步

 

从服务器脚本

 

分别在server2、server3、server4上创建同步脚本:

 

vi unisonsync.sh

 

在vi编辑器中将下列代码复制粘贴到新建的脚本中:

 

Python代码
  1. #!/bin/bash
  2. export HOME=/root
  3. echo $HOME
  4. ip=“root@192.168.0.101”
  5. src=“/var/www/html/”
  6. dst=“/var/www/html/”
  7. /usr/bin/inotifywait -mrq -e create,delete,modify,move $src | while read line; do
  8. /usr/bin/unison -batch -sshargs “-i /root/.ssh/id_rsa” $src ssh://$ip/$dst
  9. echo -n “$line “ >> /data/log/inotify.log
  10. echo `date | cut -d ” “ -f1-4` >> /data/log/inotify.log
  11. done

 

 

 

注意:

 

其中userX是指该服务器上的默认用户名。

 

授权脚本的可执行权限

 

chmod 777 ~/unisonsync.sh

 

改变需要同步的文件的访问权限:

 

chmod 777 /var/www/html

 

改变对日志目录的访问权限:

 

chmod 777 /var/log

 

 

 

主服务器上的反向设置

 

在主服务器上也创建unisonsync.sh脚本,内容如下:

 

Python代码
  1. #!/bin/bash
  2. export HOME=/root
  3. echo $HOME
  4. ip2=“root@192.168.0.102”
  5. ip3=“root@192.168.0.103”
  6. ip4=“root@192.168.0.104”
  7. src=“/var/www/html/”
  8. dst=“/var/www/html/”
  9. /usr/bin/inotifywait -mrq -e create,delete,modify,move $src | while read line; do
  10. /usr/bin/unison -batch -sshargs “-i /root/.ssh/id_rsa” $src ssh://$ip2/$dst
  11. /usr/bin/unison -batch -sshargs “-i /root/.ssh/id_rsa” $src ssh://$ip3/$dst
  12. /usr/bin/unison -batch -sshargs “-i /root/.ssh/id_rsa” $src ssh://$ip4/$dst
  13. echo -n “$line “ >> /data/log/inotify.log
  14. echo `date | cut -d ” “ -f1-4` >> /data/log/inotify.log
  15. done

 

 

 

 

其它配置与从服务器一致。

 

测试脚本

 

在server2上键入命令:

 

./unisonsync.sh&

 

然后随便复制一个文件到同步目录/var/www/html,再查看server1上的同步目录,看看该文件是否也被增加了。

 

 

 

在在server1上键入命令:

 

./unisonsync.sh&

 

然后随便复制一个文件到同步目录/var/www/html,再查看各台从服务器上的同步目录,看看该文件是否也被增加了。

 

 

 

将同步脚本设置为Centos的开机启动脚本

 

每次在服务器启动上都需要键入一遍执行脚本的命令是比较愚蠢的做法,会遭到系统维护人员的极度鄙视。明智的做法是将该启动脚本加入到Centos的开机启动脚本中去,或者使其作为Centos的服务在开机时被启动。

 

 

 

我们选择比较简洁的方式,即将该脚本添加到Centos的开机启动脚本rc.local中。/etc/rc.local是Centos开机后启动的最后一个脚本。打开编辑该脚本:

 

vi /etc/rc.local

 

在文件末尾(exit 0)之前添加如下代码:

 

/home/userX/unisonsync.sh&

 

这里userX是指该服务器上的默认用户名。

 

 

 

保存文件并重启服务器。在任意一台服务器上复制一个文件到同步目录下,看看其它服务器是否也会同步新增该文件。

 

 

OK,至此,大功告成。

 

 

 

 

 

 

 

 

 

 

0 Comments
Leave a Reply