inotify-rsync实时同步脚本
- lostsnow - 无网不剩rsync是linux下一款非常强大的同步工具,采用差异同步的方法,只上传文件/文件夹的不同部分,同时可以对上传部分先进行压缩,所以rsync的传输效率是很高的. 但rsync也有缺点,最大的问题就是每次执行rsync命令都会遍历目标目录,当文件不多时,这没什么问题,一旦文件数到了一定规模,那么每次遍历都会消耗很多资源.
2010-12-13
rsync是linux下一款非常强大的同步工具,采用差异同步的方法,只上传文件/文件夹的不同部分,同时可以对上传部分先进行压缩,所以rsync的传输效率是很高的。
但rsync也有缺点,最大的问题就是每次执行rsync命令都会遍历目标目录,当文件不多时,这没什么问题,一旦文件数到了一定规模,那么每次遍历都会消耗很多资源。但事实上改动的文件并不多,如果可以只sync改动的文件,问题就迎刃而解了。
这时就得请出本文的另一个主角:inotify。inotify是一种文件系统的变化通知机制,如文件增加、删除等事件可以立刻让用户态得知。要使用inotify,linux的内核版本不能低于2.6.13
~$ uname -a
Linux lzyy-laptop 2.6.32-26-generic #48-Ubuntu SMP Wed Nov 24 09:00:03 UTC 2010 i686 GNU/Linux
但inotify只提供了C语言接口,不方便调用,所以我们需要先安装inotify-tools,大多数的linux发行版应该都可以直接通过apt-get或yum来安装。
其实前人已经做了类似的工作,不过有些地方尚未完善(如删除文件的同步),于是我改进和简化了一下。
以下是服务端脚本,运行这段脚本后,这个机器上对应的文件夹将会同步到其他机器上
#!/bin/bash
###########################
# 在这里配置本地文件夹,目标host,目标的rsync_module。rsync_module在同步机器的/etc/rsyncd.conf文件中配置
# 逗号前后不要有空格
sync[0]='/path/to/local/dir,1.2.3.4,test' # localdir,host,rsync_module
# sync[1]='/path/to/local/dir,host,rsync_module'
###########################
for item in ${sync[@]}; do
dir=`echo $item | awk -F"," '{print $1}'`
host=`echo $item | awk -F"," '{print $2}'`
module=`echo $item | awk -F"," '{print $3}'`
inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f %e' \
--event CLOSE_WRITE,create,move,delete $dir | while read date time file event
do
echo $event'-'$file
case $event in
MODIFY|CREATE|MOVE|MODIFY,ISDIR|CREATE,ISDIR|MODIFY,ISDIR)
if [ "${file: -4}" != '4913' ] && [ "${file: -1}" != '~' ]; then
cmd="rsync -avz --exclude='*' --include=$file $dir $host::$module"
# echo $cmd
$cmd
fi
;;
MOVED_FROM|MOVED_FROM,ISDIR|DELETE|DELETE,ISDIR)
if [ "${file: -4}" != '4913' ] && [ "${file: -1}" != '~' ]; then
cmd="rsync -avz --delete-excluded --exclude="$file" $dir $host::$module"
# echo $cmd
$cmd
fi
;;
esac
done &
done
运行脚本
cd /path/to/inotify-rsync
chmod +x inotify-rsync.sh
./inotify-rsync
可以把这个脚本设置为开机启动,这样就可以自动同步了。
同步机器上要做两件事
1. 设置/etc/rsyncd.conf文件
# vim /etc/rsyncd.conf
uid=root
gid=root
# 这个test就是上面脚本中用到的rsync_module名
# path指定同步过来的文件存放的路径
# 如果只允许部分ip的机器进行同步的话,设置allow为 192.168.1.1/100 类似的格式
[test]
path=/path/to/your/dir
allow *
2. 启动rsync daemon
rsync --daemon
金山的周洋同学用C++写了个Sersync,也是利用的inotify+rsync来实现实时同步,有兴趣的可以关注一下