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,文件属性被修改,如chmod、chown、touch 等
4 IN_CLOSE_WRITE,可写文件被close
5 IN_CLOSE_NOWRITE,不可写文件被close
6 IN_OPEN,文件被open
7 IN_MOVED_FROM,文件被移走,如mv
8 IN_MOVED_TO,文件被移来,如mv、cp
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简介
rsync,remote synchronize顾名思意就知道它是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限、时间、软硬链接等附加信息。rsync是用 “rsync 算法”提供了一个客户机和远程文件服务器的文件同步的快速方法,而且可以通过ssh方式来传输文件,这样其保密性也非常好,另外它还是免费的软件。
rsync 包括如下的一些特性:
- 能更新整个目录和树和文件系统;
- 有选择性的保持符号链链、硬链接、文件属于、权限、设备以及时间等;
- 对于安装来说,无任何特殊权限要求;
- 对于多个文件来说,内部流水线减少文件等待的延时;
- 能用rsh、ssh 或直接端口做为传输入端口;
- 支持匿名rsync 同步文件,是理想的镜像工具;
sersync简介
- 利用inotify与rsync对服务器进行实时同步,其中inotify用于监控文件系统事件,rsync是目前广泛使用的同步算法,其优点是只对文件不同的部分进行操作,所以其优势大大超过使用挂接文件系统的方式进行镜像同步。由金山的周洋开发完成,是目前使用较多的文件同步工具之一。该工具和其他的工具相比有如下优点:
- sersync是使用c++编写,由于只同步发生更改的文件,因此比其他同步工具更节约时间、带宽;
- 安装方便、配置简单;
- 使用多线程进行同步,能够保证多个服务器实时保持同步状态;
- 自带出错处理机制,通过失败队列对出错的文件重新出错,如果仍旧失败,则每10个小时对同步失败的文件重新同步;
- 自带crontab功能,只需在xml配置文件中开启,即可按您的要求,隔一段时间整体同步一次;
- 自带socket与http协议扩展,你可以方便的进行二次开发;
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之后
如果ignoreError为true,则会添加>/dev/null 2>&1
当然还可以设置command的filter,当filter为ture,include可以只对正则匹配到的文件,调用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
【推荐】FlashTable:表单开发界的极速跑车,让你的开发效率一路狂飙
【推荐】Flutter适配HarmonyOS 5知识地图,实战解析+高频避坑指南
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步