#!/bin/bash
#运行该脚本前请确保主从服务器中已安装如下程序或服务,需备份服务器(master):ssh、rsync、inotify-tools;备份服务器(slave):ssh
#Synopsis:ssh-keygen+rsync+inotifywait组合,生成可从远程备份服务器slave server实时动态备份生产服务器master server数据的功能
#Function:本脚本需要本地服务器(master server)免密码登陆到备份服务器(slave server),因此需要主从服务器上均安装有ssh服务
#此版本用到rsync的ssh协议传输,所以需要用到ssh-keygen生成公私钥,该功能脚本在另一篇日志已贴出,该脚本有log日志记录功能
#为防止误操作,对于master server监视目录中delete或move from的文件或目录,将会在slave server上暂时保留,并未彻底删除
#Usage:在需要备份的服务器上运行本脚本:nohup ./inotifyRsync.sh 2>/var/log/inotify/rsyncstd_error.log &,可根据需要添加到
#/etc/rc.local,以实现开机自启
#Notes:使用本脚本要求master和slave服务器上的路径相同;运行脚本一定要当前进程执行,如果sh program执行,则有的事件无法捕捉到,
#导致同步失败
#Date:2016/11/11
#Author:Jian
#Version:v1.1
#Variable definition
############################################
inoDir="/var/log/inotify"
#slave server ip
rsServer="192.168.1.10"
#slave server username
rsUsr="root"
#master & slave server watched directory
srcDir="/home/book/watchedFolder"
#slave server directory(delete or moved_from the watched dir)
#该目录为从服务器上的备份目录,目的是为防止主服务器上误操作,从监视目录中删除文件后,从服务器会将相同
#文件先移出slave的监视目录,而移出的目标目录就是oldFiles
oldFiles="/oldFiles"
############################################
#判断master server日志目录是否存在,否则创建之
[ ! -d "$inoDir" ] && mkdir -p "$inoDir"
#判断master server 监视目录是否存在
[ ! -d $srcDir ] && mkdir -p $srcDir
#先测试是否能连接到远程主机
ping -c2 -w2 $rsUsr
if [ $? ! = 0 ];then
echo "Failed to start the synchronization due to the failed connection to the remote host $rsUsr"
exit 11
fi
#判断slave server监视目录和备份目录是否存在,否则创建之
ssh -t -q -n "$rsUsr"@"$rsServer" "[ ! -d "$srcDir" ] && mkdir -p "$srcDir""
ssh -t -q -n "$rsUsr"@"$rsServer" "[ ! -d "$oldFiles" ] && mkdir -p "$oldFiles""
#master 开启inotifywait,监视指定目录
/usr/local/inotify-3.14/bin/inotifywait -mrq -e close_write,create,moved_to,moved_from,attrib,delete \
--format '%w*%f*%Xe' $srcDir | tee $inoDir/inotify_events.`date +%Y%m%d`.log \
| while read line
do
#inotifywait命令输出格式如:/rsbackup/rs/*backup*MOVED_FROMXISDIR
inoPath=$(echo $line | awk -F"*" '{print $1}') #inotifywait命令输出分段,eg:inoPath=/rsbackup/rs/
inoFile=$(echo $line | awk -F"*" '{print $2}') #eg:inoFile=backup
inoAction=$(echo $line | awk -F"*" '{print $3}') #eg:inoAction=MOVED_FROMXISDIR
rsyncSuccess=$inoDir/rsync_success.`date +%Y%m%d`.log #rsync同步成功记录日志
rsyncError=$inoDir/rsync_error.`date +%Y%m%d`.log #rsync同步失败记录日志
#下面对捕捉到的inotifywait输出的每一个Filename和Action分别处理
#file or dir moved from start location
if [ "$inoAction" = "MOVED_FROM" ] || [ "$inoAction" = "MOVED_FROMXISDIR" ] || [ "$inoAction" = "DELETE" ] || [ "$inoAction" = "DELETEXISDIR" ]
then
#注意这里的ssh命令必须加-n选项,在while循环中调用ssh命令,ssh会把当前输入中所有的数据读走,即重定向
#给while命令的数据,都会被ssh命令读走,以至于下次循环的时候,read读到的内容为空,导致循环提前结束,加-n避免这一情况
ssh -t -q -n "$rsUsr"@"$rsServer" "[ -d "$inoPath$inoFile" ] || [ -f "$inoPath$inoFile" ] && mv $inoPath$inoFile "$oldFiles""
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE OR DIR(moved from successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE OR DIR(file or dir moved from failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file or dir moved from end location
#new file create start location
echo "$inoFile" | grep -Ev "\...*sw[a-z]x?$" > /dev/null #grep -Ev用于排除正在编辑的.swx/.swp/.swpx等临时文件
if [ $? -eq 0 ];then
if [ "$inoAction" = "CLOSE_WRITEXCLOSE" ];then
rsync -ahzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath" #rsync同步
if [ $? -eq 0 ];then #判断上面的rsync同步是否成功执行,否则生成传输错误日志
echo "`date "+%Y%m%d%H%M%S"` : FILE(create or edit or cp -af successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(create or edit or cp -af failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
fi
#new file create end location
#file renamed or moved start location
if [ "$inoAction" = "MOVED_TO" ] ;then
rsync -ahzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE(renamed or moved successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(renamed or moved failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file renamed or moved end location
#dir create or cp -r start location
if [ "$inoAction" = "CREATEXISDIR" ];then
rsync -aruzc -d -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(create or cp -r successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(create or cp -r failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir create or cp -r end location
#dir renamed or moved to start location
if [ "$inoAction" = "MOVED_TOXISDIR" ];then
rsync -aruzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(renamed or moved to successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(renamed or moved to failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir renamed or moved to end location
#file attrib changed start location
if [ "$inoAction" = "ATTRIB" ];then
rsync -aruzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE(attribute changed successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(attribute changed failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file attrib changed end location
#dir attrib changed start location
if [ "$inoAction" = "ATTRIBXISDIR" ] && [ -n "$inoFile" ];then
rsync -auzc -d -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(attribute changed successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(attribute changed failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir attrib changed end location
done
#运行该脚本前请确保主从服务器中已安装如下程序或服务,需备份服务器(master):ssh、rsync、inotify-tools;备份服务器(slave):ssh
#Synopsis:ssh-keygen+rsync+inotifywait组合,生成可从远程备份服务器slave server实时动态备份生产服务器master server数据的功能
#Function:本脚本需要本地服务器(master server)免密码登陆到备份服务器(slave server),因此需要主从服务器上均安装有ssh服务
#此版本用到rsync的ssh协议传输,所以需要用到ssh-keygen生成公私钥,该功能脚本在另一篇日志已贴出,该脚本有log日志记录功能
#为防止误操作,对于master server监视目录中delete或move from的文件或目录,将会在slave server上暂时保留,并未彻底删除
#Usage:在需要备份的服务器上运行本脚本:nohup ./inotifyRsync.sh 2>/var/log/inotify/rsyncstd_error.log &,可根据需要添加到
#/etc/rc.local,以实现开机自启
#Notes:使用本脚本要求master和slave服务器上的路径相同;运行脚本一定要当前进程执行,如果sh program执行,则有的事件无法捕捉到,
#导致同步失败
#Date:2016/11/11
#Author:Jian
#Version:v1.1
#Variable definition
############################################
inoDir="/var/log/inotify"
#slave server ip
rsServer="192.168.1.10"
#slave server username
rsUsr="root"
#master & slave server watched directory
srcDir="/home/book/watchedFolder"
#slave server directory(delete or moved_from the watched dir)
#该目录为从服务器上的备份目录,目的是为防止主服务器上误操作,从监视目录中删除文件后,从服务器会将相同
#文件先移出slave的监视目录,而移出的目标目录就是oldFiles
oldFiles="/oldFiles"
############################################
#判断master server日志目录是否存在,否则创建之
[ ! -d "$inoDir" ] && mkdir -p "$inoDir"
#判断master server 监视目录是否存在
[ ! -d $srcDir ] && mkdir -p $srcDir
#先测试是否能连接到远程主机
ping -c2 -w2 $rsUsr
if [ $? ! = 0 ];then
echo "Failed to start the synchronization due to the failed connection to the remote host $rsUsr"
exit 11
fi
#判断slave server监视目录和备份目录是否存在,否则创建之
ssh -t -q -n "$rsUsr"@"$rsServer" "[ ! -d "$srcDir" ] && mkdir -p "$srcDir""
ssh -t -q -n "$rsUsr"@"$rsServer" "[ ! -d "$oldFiles" ] && mkdir -p "$oldFiles""
#master 开启inotifywait,监视指定目录
/usr/local/inotify-3.14/bin/inotifywait -mrq -e close_write,create,moved_to,moved_from,attrib,delete \
--format '%w*%f*%Xe' $srcDir | tee $inoDir/inotify_events.`date +%Y%m%d`.log \
| while read line
do
#inotifywait命令输出格式如:/rsbackup/rs/*backup*MOVED_FROMXISDIR
inoPath=$(echo $line | awk -F"*" '{print $1}') #inotifywait命令输出分段,eg:inoPath=/rsbackup/rs/
inoFile=$(echo $line | awk -F"*" '{print $2}') #eg:inoFile=backup
inoAction=$(echo $line | awk -F"*" '{print $3}') #eg:inoAction=MOVED_FROMXISDIR
rsyncSuccess=$inoDir/rsync_success.`date +%Y%m%d`.log #rsync同步成功记录日志
rsyncError=$inoDir/rsync_error.`date +%Y%m%d`.log #rsync同步失败记录日志
#下面对捕捉到的inotifywait输出的每一个Filename和Action分别处理
#file or dir moved from start location
if [ "$inoAction" = "MOVED_FROM" ] || [ "$inoAction" = "MOVED_FROMXISDIR" ] || [ "$inoAction" = "DELETE" ] || [ "$inoAction" = "DELETEXISDIR" ]
then
#注意这里的ssh命令必须加-n选项,在while循环中调用ssh命令,ssh会把当前输入中所有的数据读走,即重定向
#给while命令的数据,都会被ssh命令读走,以至于下次循环的时候,read读到的内容为空,导致循环提前结束,加-n避免这一情况
ssh -t -q -n "$rsUsr"@"$rsServer" "[ -d "$inoPath$inoFile" ] || [ -f "$inoPath$inoFile" ] && mv $inoPath$inoFile "$oldFiles""
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE OR DIR(moved from successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE OR DIR(file or dir moved from failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file or dir moved from end location
#new file create start location
echo "$inoFile" | grep -Ev "\...*sw[a-z]x?$" > /dev/null #grep -Ev用于排除正在编辑的.swx/.swp/.swpx等临时文件
if [ $? -eq 0 ];then
if [ "$inoAction" = "CLOSE_WRITEXCLOSE" ];then
rsync -ahzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath" #rsync同步
if [ $? -eq 0 ];then #判断上面的rsync同步是否成功执行,否则生成传输错误日志
echo "`date "+%Y%m%d%H%M%S"` : FILE(create or edit or cp -af successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(create or edit or cp -af failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
fi
#new file create end location
#file renamed or moved start location
if [ "$inoAction" = "MOVED_TO" ] ;then
rsync -ahzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE(renamed or moved successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(renamed or moved failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file renamed or moved end location
#dir create or cp -r start location
if [ "$inoAction" = "CREATEXISDIR" ];then
rsync -aruzc -d -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(create or cp -r successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(create or cp -r failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir create or cp -r end location
#dir renamed or moved to start location
if [ "$inoAction" = "MOVED_TOXISDIR" ];then
rsync -aruzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(renamed or moved to successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(renamed or moved to failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir renamed or moved to end location
#file attrib changed start location
if [ "$inoAction" = "ATTRIB" ];then
rsync -aruzc -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : FILE(attribute changed successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : FILE(attribute changed failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#file attrib changed end location
#dir attrib changed start location
if [ "$inoAction" = "ATTRIBXISDIR" ] && [ -n "$inoFile" ];then
rsync -auzc -d -e ssh "$inoPath$inoFile" "$rsUsr"@"$rsServer":"$inoPath"
if [ $? -eq 0 ];then
echo "`date "+%Y%m%d%H%M%S"` : DIR(attribute changed successfuly) : $inoPath$inoFile" >> $rsyncSuccess
else
echo "`date "+%Y%m%d%H%M%S"` : DIR(attribute changed failure) : $inoPath$inoFile" >> $rsyncError
fi
fi
#dir attrib changed end location
done