Sersync实现触发式文件同步

言:如果我们后端有多台网站服务器或者文件服务器,而且没有好的文件同步机制,那么当我们升级程序或者更新文件的时候,就需要每台服务器或者目录都要更 新,这样很容易出问题,并很容易导致两边的文件不一致,从而出现很多莫民其妙的问题。因此我们需要使用好的文件同步方式来实现几个后端服务器文件的同步, 目前广泛采用的方案是使用rsync+inotify的方式来实现文件的触发更新。原理是采用inotify来对文件进行监控,当监控到文件有文件发生改变的时候,就会调用rsync实现触发式实时同步!本文就来详细介绍金山的一个居于inotify+rsync进行二次开发实现文件同步的小工具sersync,能够很方便的实现文件触发式同步

inotify简介

是基于inode级别的文件系统监控技术,是一种强大的、细粒度的、异步的机制,它满足各种各样的文件监控需要,不仅限于安全和性能,内核要求2.6.13以上,inotify能监控非常多的文件系统事件,通过监控这些事件来监控文件是否发生变更,然后通过rsync来更新发生变更的文件,Inotify 可以监视的文件系统事件包括:

1 IN_ACCESS,即文件被访问

2 IN_MODIFY,文件被write

3 IN_ATTRIB,文件属性被修改,如chmodchowntouch

4 IN_CLOSE_WRITE,可写文件被close

5 IN_CLOSE_NOWRITE,不可写文件被close

6 IN_OPEN,文件被open

7 IN_MOVED_FROM,文件被移走,mv

8 IN_MOVED_TO,文件被移来,如mvcp

9 IN_CREATE,创建新文件

10 IN_DELETE,文件被删除,如rm

11 IN_DELETE_SELF,自删除,即一个可执行文件在执行时删除自己

12 IN_MOVE_SELF,自移动,即一个可执行文件在执行时移动自己

13 IN_UNMOUNT,宿主文件系统被umount

14 IN_CLOSE,文件被关闭,等同于(IN_CLOSE_WRITE |IN_CLOSE_NOWRITE)

15 IN_MOVE,文件被移动,等同于(IN_MOVED_FROM | IN_MOVED_TO)

备注:上面的文件也包括目录。

Rsync简介

 rsyncremote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息。rsync是用 “rsync 算法提供了一个客户机和远程文件服务器的文件同步的快速方法,而且可以通过ssh方式来传输文件,这样其保密性也非常好,另外它还是免费的软件。

rsync 包括如下的一些特性:

  • 能更新整个目录和树和文件系统;
  • 有选择性的保持符号链链、硬链接、文件属于、权限、设备以及时间等;
  • 对于安装来说,无任何特殊权限要求;
  • 对于多个文件来说,内部流水线减少文件等待的延时;
  • 能用rshssh 或直接端口做为传输入端口;
  • 支持匿名rsync 同步文件,是理想的镜像工具;

sersync简介

  • 利用inotifyrsync对服务器进行实时同步,其中inotify用于监控文件系统事件,rsync是目前广泛使用的同步算法,其优点是只对文件不同的部分进行操作,所以其优势大大超过使用挂接文件系统的方式进行镜像同步。由金山的周洋开发完成,是目前使用较多的文件同步工具之一。该工具和其他的工具相比有如下优点:
  • sersync是使用c++编写,由于只同步发生更改的文件,因此比其他同步工具更节约时间、带宽;
  • 安装方便、配置简单;
  • 使用多线程进行同步,能够保证多个服务器实时保持同步状态;
  • 自带出错处理机制,通过失败队列对出错的文件重新出错,如果仍旧失败,则每10个小时对同步失败的文件重新同步;
  • 自带crontab功能,只需在xml配置文件中开启,即可按您的要求,隔一段时间整体同步一次;
  • 自带sockethttp协议扩展,你可以方便的进行二次开发;

sersync实现触发式文件同步实战

    • 服务器文件同步图

   从服务器的安装配置

安装rsync

yum -y install rsync

配置rsync

vim  /etc/rsyncd.conf

# Rsync configuration file

uid = root

gid = root

port = 873

max connections = 20000

use chroot = yes

timeout = 200

log file = /var/log/rsyncd.log

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsyncd.lock

log format = %t %a %m %f %b

auth users = root

secrets file = /etc/rsyncd.secret

 

[test]

path = /data/wwwroot/

comment = "test directory file"

list = yes

read only = no

ignore errors = yes

hosts allow = 192.168.3.205

hosts deny = *

vim /etc/rsyncd.secret

root:abc123@#$

Chmod 600 /etc/rsyncd.secret

600权限,不然同步的时候会报password file must not be other-accessible错误

Rsync的启动

启动有两种方式,两种方式哪一种都可以,读者可以自行选择:

daemon的方式启动:

/usr/bin/rsync --daemon --config=/etc/rsyncd.conf

 

xinetd集成启动方式:

chkconfig rsync on

chkconfig xinetd on

/etc/init.d/xinetd start

验证rsync是否启动

[root@test_machine test]# ps aux | grep rsync

root     3275  0.0  0.0 65516   472 ?        Ss  13:44   0:00 /usr/bin/rsync--daemon --config=/etc/rsyncd.conf

root     3306  0.0  0.1 71812   936 ?        S   14:49   0:00 /usr/bin/rsync--daemon --config=/etc/rsyncd.conf

[root@test_machine test]# netstat -lnp | grep rsync

tcp        0      0 0.0.0.0:873                 0.0.0.0:*                   LISTEN      3275/rsync          

tcp       0      0 :::873                      :::*                        LISTEN      3275/rsync

主服务器的安装配置

安装rsync

yum -y install rsync

安装sersync

wget  http://sersync.googlecode.com/files/sersync2.5.4_64bit_binary_stable_final.tar.gz

tar xzvfsersync2.5_64bit_binary_stable_final.tar.gz

mv GNU-Linux-x86 /usr/local/sersync

配置sersync

<head version="2.5">

<host hostip="localhost" port="8008"></host>

   <debug start="false"/>

   <fileSystem xfs="false"/>

  <filter start="false">

 <exclude expression="(.*)\.svn"></exclude>

  <exclude expression="(.*)\.gz"></exclude>

  <exclude expression="^info/*"></exclude>

  </filter>

    <inotify>

      <delete start="true"/>

      <createFolder start="true"/>

      <createFile start="true"/>

      <closeWrite start="true"/>

      <moveFrom start="true"/>

      <moveTo start="true"/>

      <attrib start="true"/>

      <modify start="true"/>

</inotify>

     <sersync>

     <localpath watch="/data/test">

 <remote ip="192.168.3.203" name="test"/>

 </localpath>

      <rsync>

   <commonParams params="-artuz"/>

  <auth start="true" users="root" passwordfile="/etc/rsyncd.secret"/>

      <userDefinedPort start="true" port="873"/>

         <timeout start="false" time="100"/>

           <ssh start="false"/>

       </rsync>

       <failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/>

       <crontab start="false" schedule="600"><!--600mins-->

           <crontabfilter start="false">

                <exclude expression="*.php"></exclude>

               <exclude expression="info/*"></exclude>

            </crontabfilter>

        </crontab>

        <plugin start="false" name="command"/>

       </sersync>

 

  <plugin name="command">

        <param prefix="/bin/sh" suffix="" ignoreError="true"/>

       <filter start="false">

            <include expression="(.*)\.php"/>

            <include expression="(.*)\.sh"/>

       </filter>

       </plugin>

</head>

 

 

vim /etc/rsyncd.secret

abc123@#$

Chmod 600 /etc/rsyncd.sercret

启动sersync

/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml

echo /usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml >> /etc/rc.local

以后重启系统以后才能正常同步

脚本监控sersync

sersync脚本会自动关掉,因此需要写一个脚本自动的去检测该进程是否存在,不存在就启动,脚本内容如下:

vim  check_sersync.sh

#!/bin/bash

# usage:

#1.Copy Shell To SersyncPath

#       chmod +x checkrsync.sh

#       2.Add Crontab

#       */5 * * * * [sersyncPath]/checkrsync.sh

 

logfile='/var/log/sersync/checksersync.log';

 

function sersync_is_running(){

threadnum=`ps aux|grep sersync2|grep -v grep -wc`;

if [ "$threadnum" -eq '0' ];then

echo '0';

else

echo '1';

fi

return;

}

 

function current_time(){

if [ -z "$1" ];then

                format="%Y-%m-%d %H:%M:%S%Z";

        else

                format=$1;

        fi

        echo `date +"$format"`;

        return;

}

 

function logtofile(){

echo $(current_time) $2>>$1;

}

 

function sersync_restart(){

/usr/local/sersync/sersync2 -r -d -o /usr/local/sersync/confxml.xml >/dev/null 2>&1;

sleep 3;

 

threadnum=$(sersync_is_running);

if [ $threadnum -eq '0' ]; then

echo "0";

else

echo '1';

fi

return;

}

 

isrunning=$(sersync_is_running);

 

if [ "$isrunning" -eq '0' ];then

logtofile $logfile "sersync service was died.";

 

restart=$(sersync_restart);

 

if [ $restart -eq '0' ];then

logtofile $logfile "sersync service restart failed.";

else

logtofile $logfile "sersync service restart success.";

fi

else

logtofile $logfile "sersync service is running.";

fi

 

exit 0;

 

 

crontab -e

*/5 * * * * /root/tools/check_sersync.sh >/dev/null 2>&1

sersync脚本有时候会卡死,因此需要隔一段时间重启一下,脚本内容如下:

Vim sersync.sh

 

#!/bin/bash

set -x

SERSYNC="/usr/local/sersync/sersync2"

CONF_FILE="/usr/local/sersync/confxml.xml"

PIDSTAT=`ps -ef |grep 'confxml.xml' |grep -v grep |awk '{print $2}'`

kill -9 $PIDSTAT

#pkill  sersync2

#pkill  sersync2

rm -rf /tmp/rsync_fail_log.sh

STATUS=$(ps aux |grep 'confxml.xml'|grep -v 'grep'|wc -l)

if [ $STATUS -eq 0 ];

 

then

       

       $SERSYNC -d  -r -o $CONF_FILE &

 

else

 

       exit 0;

 

Fi

 

crontab -e

 

0 */10 * * * /root/tools/sersync.sh >/dev/null 2>&1

 

总结:通过以上几步以后,你从服务器的/data/test就能够从主服务器实时更新,升级的时候只升级主服务器的文件,从服务器也会自动同步过去,减少你的工作量以及出错的概率!如果读者想了解更多的信息,请直接访问sersync开发者的博客,博客里有更详细的说明!

http://blog.johntechinfo.com/sersyncguild

插件相关

如上面的xml所示,其中plugin标签设置为true时候,在同步文件或路径到远程之后后,调用插件。通过name参数指定需要执行的插件。目前支持的有command refreshCDN socket http四种插件。http插件目前由于兼容性原因去除,以后会重新加入。

以下模块(command refreshCDN http socket)可以单独使用(发生文件改变不同步只调用插件),只需在命令行下使用-m 参数即可。如果需要作为插件与同步程序一起使用,见同步程序说明的插件配置。

command插件

<plugin name="command">

        <param prefix="/bin/sh" suffix="" ignoreError="true"/>

       <filter start="false">

            <include expression="(.*)\.php"/>

            <include expression="(.*)\.sh"/>

       </filter>

 </plugin>

当文件同步完成后,会调用command插件,如同步文件是test.php,则test.php文件在改动之后,调用rsync同步到远程服务器后,调用command插件,执行

/bin/sh test.php  suffix >/dev/null 2>&1

如果suffix 设置了,则会放在inotify事件test.php之后
如果ignoreErrortrue,则会添加>/dev/null 2>&1
当然还可以设置commandfilter,当filtertureinclude可以只对正则匹配到的文件,调用command

refreshCDN 插件

“refreshCDN”,就在同步过程中将文件发送到目 的服务器后刷新cdn接口。如果不想使用,则将start属性设为false即可。如果需要使用其他插件,则查看其他plugin标签,将插件名称改为 xml中其它插件的名称即可。该模块根据chinaCDN的协议,进行设计,当有文件产生的时候,就向cdn接口发送需要刷新的路径位置。刷新CDN模块 需要配置的xml文件如下。

 

<plugin name="refreshCDN">

<localpath watch="/data0/htdocs/cms.xoyo.com/site/">

<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>

<sendurl base="http://pic.xoyo.com/cms"/>

<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>

</localpath>

</plugin>

其中 localpath watch 是需要监控的目录。

cdnifo标签制定了cdn接口的域名,端口号,以及用户名与密码。

sendurl标签是需要刷新的url的前缀。

regexurl标签中的,regex属性为true时候,使用match属性的正则语句匹配inotify返回的路径信息,并将正则匹配到的部分作为url一部分,

举例:

如果产生文件事件为:/data0/htdoc/cms.xoyo.com/site/jx3.xoyo.com/image/a/123.txt

经过上面的match正则匹配后,最后刷新的路径是:

http://pic.xoyo.com/cms/jx3/a/123.txt;

如果regex属性为false,最后刷新的路径是

http://pic.xoyo.com/cms/jx3.xoyo.com/images/a/123.txt;

socket插件

socket插件,开启该模块,则向指定ip与端口发送inotify所产生的文件路径信息。

Http插件

http插件,可以向指定域名的主机post,inotify监控的事件。


单独运行插件

插件也可以单独使用,即不对远程目标机进行同步,直接调用插件:

只调用command插件

./sersync -d -m command

只调用refreshCDN插件

./sersync -d -m refreshCDN

只调用socket插件

./sersync -d -m socket

只调用http插件

./sersync -d -m http

 

posted @ 2018-03-09 08:53  屌丝的IT  阅读(378)  评论(0)    收藏  举报
点击右上角即可分享
微信分享提示