1、单纯使用rsync加入计划任务只能设置最少1分钟的间隔,而使用inotify事件触发小文件为秒级同步,取决于网速,和写入磁盘的速度

2、此脚本只对移动到监控的目录、监控目录中的目录有重命名的情况进行递归同步

3、其它需要进行同步的操作:

rsync+inotifywait实现数据实时同步(上篇:分析inotifywait产生的事件)

4、inotify-tools的安装:

安装inotify工具inotify-tools(inotifywait和inotifywatch)


注:

使用本脚本要求需要同步的服务器上的路径相同!


因为考虑到误删除的问题,所以本脚本没有使用同步删除功能,以后如果需要再添加……


一定要当前进程执行!如果sh program执行有的事件无法捕捉到,导致同步失败。


运行方式:

假设此脚本放在/下:

在/etc/rc.local中添加开机自启动、后台运行(为了方便排错推荐重定向错误到文件,如果有内容的话也应该是system()函数中的rsync错误):

有日志功能:

. /rsync_inotify_log.sh 2>/var/log/rsync_inotify.error >&2 &

无日志功能:

. /rsync_inotify_nolog.sh >/var/log/rsync_inotify.log 2>/var/log/rsync_inotify.error &


以下两个脚本,区别在于有日志功能和无日志功能(都已测试,推荐使用有日志功能的)


有日志功能:rsync_inotify_log.sh

#!/bin/bash
#exec like:". program &",and don't like:"/bin/bash program &",(some events cannot be processed(pipe?))
#you can add above command line into /etc/rc.local
inotify_d="/var/log/inotify"
if [ ! -d "$inotify_d" ];then
    mkdir $inotify_d
fi
/usr/local/bin/inotifywait -mrq -e close_write,close_nowrite,create,moved_to,attrib,delete \
--format '%w*%f*%Xe' /tmp/rs\ ync/rs | tee $inotify_d/inotify_events.`date +%Y%m%d`.log |
/bin/awk -v inotify_d=$inotify_d '
BEGIN{
    FS="*"
    r_host="192.168.2.120"
}
function bslash(line,  dpath) {
                  
        if (dpath==1)
        {
                gsub(/ /,"\\\\&",line)
                gsub(/^/,"\"",line)
                gsub(/$/,"\"",line)
        }
        else
        {
                gsub(/ /,"\\\\&",line)
        }
        return line
}
{
    inotify_t=strftime("%Y%m%d")
    rsync_success=inotify_d"/rsync_success."inotify_t".log"
    rsync_error=inotify_d"/rsync_error."inotify_t".log"
    #SFTP file renamed start
    if ($3 ~ /^CREATE$/)
    {
        sftp_renamed_f=bslash($2)
        sftp_renamed_f_path=bslash($1)
        sftp_renamed_f_path_dest=bslash($1,1)
    }
    else if ($3 ~ /^DELETE$/)
    {
        if (sftp_renamed_f != "")
        {
            if (system("/usr/bin/rsync -ulDtpog -e ssh "sftp_renamed_f_path \
            sftp_renamed_f" "r_host":"sftp_renamed_f_path_dest)==0)
            {
                print strftime("%Y%m%d%H%M%S")" : FILE(sftp renamed) : " \
            sftp_renamed_f_path sftp_renamed_f >>rsync_success
                close(rsync_success)
            }
            else
            {
                print strftime("%Y%m%d%H%M%S")" : FILE(sftp renamed) : " \
            sftp_renamed_f_path sftp_renamed_f >>rsync_error
                close(rsync_error)
            }
            sftp_renamed_f=""
            sftp_renamed_f_path=""
            sftp_renamed_f_path_dest=""
        }
    }
    else
    {
        sftp_renamed_f=""
        sftp_renamed_f_path=""
        sftp_renamed_f_path_dest=""
    }
    #SFTP file renamed end
    #new file create start
    if ($3 ~ /^CLOSE_WRITEXCLOSE$/ && ($2 !~ /\...*sw[a-z]x?$/))
    {
      if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
      {
        print strftime("%Y%m%d%H%M%S")" : FILE(create or cp -af) : "$1$2 >>rsync_success
        close(rsync_success)
      }
      else
      {
        print strftime("%Y%m%d%H%M%S")" : FILE(create or cp -af) : "$1$2 >>rsync_error
        close(rsync_error)
      }
    }
    #new file create end
    #file renamed or moved start
    if ($3 ~ /^MOVED_TO$/)
    {
      if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
      {
        print strftime("%Y%m%d%H%M%S")" : FILE(renamed or moved) : "$1$2 >>rsync_success
        close(rsync_success)
      }
      else
      {
        print strftime("%Y%m%d%H%M%S")" : FILE(renamed or moved) : "$1$2 >>rsync_error
        close(rsync_error)
      }
    }
    #file renamed or moved end
    #dir create or cp -r start
    if ($3 ~ /^CREATEXISDIR$/)
    {
      if (system("/usr/bin/rsync -ulDtpog -d -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
      {
        print strftime("%Y%m%d%H%M%S")" : DIR(create or cp -r) : "$1$2 >>rsync_success
        close(rsync_success)
      }
      else
      {
        print strftime("%Y%m%d%H%M%S")" : DIR(create or cp -r) : "$1$2 >>rsync_error
        close(rsync_error)
      }
    }
    #dir create or cp -r end
    #dir renamed or moved start
    if ($3 ~ /^MOVED_TOXISDIR$/)
    {
     if (system("/usr/bin/rsync -ulDtpog -r -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
      {
        print strftime("%Y%m%d%H%M%S")" : DIR(renamed or moved) : "$1$2 >>rsync_success
        close(rsync_success)
      }
      else
      {
        print strftime("%Y%m%d%H%M%S")" : DIR(renamed or moved) : "$1$2 >>rsync_error
        close(rsync_error)
      }
    }
    #dir renamed or moved end
    #dir attrib changed start
    if ($3 ~ /^ATTRIBXISDIR$/ && $2 != "")
    {
        if ($2 in last_ad_c)
        {
            if ((++last_ad_c[$2]) == 4)
            {
                for (dnr in a_d)
                {
                        if (system("/usr/bin/rsync -ulDtpog -d -e ssh " \
                    a_d_path[dnr] a_d[dnr]" "r_host":"a_d_path_dest[dnr])==0)
                    {
                        print strftime("%Y%m%d%H%M%S")" : DIR(attrib changed) : " \
                        a_d_path[dnr] a_d[dnr] >>rsync_success
                        close(rsync_success)
                    }
                    else
                    {
                        print strftime("%Y%m%d%H%M%S")" : DIR(attrib changed) : " \
                        a_d_path[dnr] a_d[dnr] >>rsync_error
                        close(rsync_error)
                    }
                }
                delete last_ad_c
                delete a_d
                delete a_d_path
                delete a_d_path_dest
            }
                      
        }
        else
        {
                ++last_ad_c[$2]
                a_d[NR]=bslash($2)
                a_d_path[NR]=bslash($1)
                a_d_path_dest[NR]=bslash($1,1)
        }
              
    }
    else if ($3 ~ /^CLOSE_NOWRITEXCLOSEXISDIR$/ && $2 == "")
    {
        for (dnr in a_d)
        {
                if (system("/usr/bin/rsync -ulDtpog -d -e ssh "a_d_path[dnr] a_d[dnr] \
            " "r_host":"a_d_path_dest[dnr])==0)
            {
                print strftime("%Y%m%d%H%M%S")" : DIR(attrib changed) : " \
                a_d_path[dnr] a_d[dnr] >>rsync_success
                close(rsync_success)
            }
            else
            {
                print strftime("%Y%m%d%H%M%S")" : DIR(attrib changed) : " \
                a_d_path[dnr] a_d[dnr] >>rsync_error
                close(rsync_error)
            }
        }
        delete last_ad_c
        delete a_d
        delete a_d_path
        delete a_d_path_dest
    }
    else
        ;
    #dir attrib changed end
    #file attrib changed start
    if ($3 ~ /^CREATE$/)
        cp_f[NR]=$2
    if ($3 ~ /^ATTRIB$/)
    {
        if (--NR in cp_f)
            last_cp_f=$2
        if ($2 != last_cp_f)
        {
            if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1) bslash($2) \
            " "r_host":"bslash($1,1))==0)
            {
                print strftime("%Y%m%d%H%M%S")" : FILE(attrib changed) : " \
                a_d_path[dnr] a_d[dnr] >>rsync_success
                close(rsync_success)
            }
            else
            {
                print strftime("%Y%m%d%H%M%S")" : FILE(attrib changed) : " \
                a_d_path[dnr] a_d[dnr] >>rsync_error
                close(rsync_error)
            }
            last_cp_f=""
        }
    }
    #file attrib changed end
}'

无日志功能:rsync_inotify_nolog.sh

#!/bin/bash
/usr/local/bin/inotifywait -mrq -e close_write,close_nowrite,create,moved_to,attrib,delete \
--format '%w*%f*%Xe' /tmp/rs\ ync/rs |
/bin/awk '
BEGIN{
    FS="*"
    r_host="192.168.2.120"
}
function bslash(line,  dpath) {
                
        if (dpath==1)
        {
                gsub(/ /,"\\\\&",line)
                gsub(/^/,"\"",line)
                gsub(/$/,"\"",line)
        }
        else
        {
                gsub(/ /,"\\\\&",line)
        }
        return line
}
{
    #SFTP file renamed start
    if ($3 ~ /^CREATE$/)
    {
        sftp_renamed_f=bslash($2)
        sftp_renamed_f_path=bslash($1)
        sftp_renamed_f_path_dest=bslash($1,1)
    }
    else if ($3 ~ /^DELETE$/)
    {
        if (sftp_renamed_f != "")
        {
            if (system("/usr/bin/rsync -ulDtpog -e ssh "sftp_renamed_f_path \
            sftp_renamed_f" "r_host":"sftp_renamed_f_path_dest)==0)
                print "FILE(sftp renamed): "sftp_renamed_f_path sftp_renamed_f
            sftp_renamed_f=""
            sftp_renamed_f_path=""
            sftp_renamed_f_path_dest=""
        }
    }
    else
    {
        sftp_renamed_f=""
        sftp_renamed_f_path=""
        sftp_renamed_f_path_dest=""
    }
    #SFTP file renamed end
    #new file create start
    if ($3 ~ /^CLOSE_WRITEXCLOSE$/ && ($2 !~ /\...*sw[a-z]x?$/))
    {
      if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
        print "FILE(create or cp -af): "$1$2
    }
    #new file create end
    if ($3 ~ /^MOVED_TO$/)
    {
        if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
            print "FILE(renamed or moved): "$1$2
    }
    if ($3 ~ /^CREATEXISDIR$/)
    {
         if (system("/usr/bin/rsync -ulDtpog -d -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
            print "DIR(create or cp -r): "$1$2
    }
    if ($3 ~ /^MOVED_TOXISDIR$/)
    {
     if (system("/usr/bin/rsync -ulDtpog -r -e ssh "bslash($1)bslash($2)" "r_host":"bslash($1,1))==0)
        print "DIR(renamed or moved): "$1$2
    }
    #dir attrib changed start
    if ($3 ~ /^ATTRIBXISDIR$/ && $2 != "")
    {
        if ($2 in last_ad_c)
        {
            if ((++last_ad_c[$2]) == 4)
            {
                for (dnr in a_d)
                {
                        if (system("/usr/bin/rsync -ulDtpog -d -e ssh " \
                    a_d_path[dnr] a_d[dnr]" "r_host":"a_d_path_dest[dnr])==0)
                        print "DIR(attrib changed): "a_d_path[dnr] a_d[dnr]
                }
                delete last_ad_c
                delete a_d
                delete a_d_path
                delete a_d_path_dest
            }
                    
        }
        else
        {
                ++last_ad_c[$2]
                a_d[NR]=bslash($2)
                a_d_path[NR]=bslash($1)
                a_d_path_dest[NR]=bslash($1,1)
        }
            
    }
    else if ($3 ~ /^CLOSE_NOWRITEXCLOSEXISDIR$/ && $2 == "")
    {
        for (dnr in a_d)
        {
                if (system("/usr/bin/rsync -ulDtpog -d -e ssh "a_d_path[dnr] a_d[dnr] \
            " "r_host":"a_d_path_dest[dnr])==0)
            print "DIR(attrib changed): "a_d_path[dnr] a_d[dnr]
        }
        delete last_ad_c
        delete a_d
        delete a_d_path
        delete a_d_path_dest
    }
    else
        ;
    #dir attrib changed end
            
    #file attrib changed start
    if ($3 ~ /^CREATE$/)
        cp_f[NR]=$2
    if ($3 ~ /^ATTRIB$/)
    {
        if (--NR in cp_f)
            last_cp_f=$2
        if ($2 != last_cp_f)
        {
            if (system("/usr/bin/rsync -ulDtpog -e ssh "bslash($1) bslash($2) \
            " "r_host":"bslash($1,1))==0)
            print "FILE(attrib changed): " $1$2
            last_cp_f=""
        }
    }
    #file attrib changed end
}'