ssh-keygen+rsync+inotifywait实现数据实时动态同步

本文介绍了一种利用inotifywait、rsync及ssh-keygen实现的实时数据同步脚本,适用于主从服务器间的数据备份场景。该脚本能有效监控文件变动,并通过rsync进行实时同步。
#!/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
在使用 `rsync` 实现文件的实时同步时,通常需要结合其他工具或机制来触发同步操作。`rsync` 本身并不提供真正的“实时同步功能,但可以通过与 `inotify`(Linux 文件系统事件监控工具)配合,实现当文件发生变化时立即进行同步。 ### 配置方法 #### 1. 使用 `lsyncd` 实现实时同步 `lsyncd` 是一个轻量级的工具,能够监听目录变化并自动调用 `rsync` 进行同步。以下是配置示例: - **安装 lsyncd** 在 Ubuntu 或 Debian 系统上: ```bash sudo apt-get install lsyncd ``` - **配置文件 `/etc/lsyncd.conf` 示例** 下面是一个典型的配置片段,用于监听本地目录并在发生更改时同步到远程服务器: ```lua settings { logfile = "/var/log/lsyncd.log", statusFile = "/tmp/lsyncd.status" } sync { default.rsync, source = "/path/to/local/directory", target = "remote_host:/path/to/remote/directory", rsync = { archive = true, compress = false, verbose = true } } ``` 此配置会监控指定的本地目录,并将任何变更通过 `rsync` 同步到目标主机的指定路径 [^4]。 - **启动 lsyncd** ```bash sudo systemctl start lsyncd sudo systemctl enable lsyncd ``` #### 2. 使用 inotify-tools 手动编写脚本 如果不想使用 `lsyncd`,可以利用 `inotify-tools` 编写自定义脚本来实现实时同步- **安装 inotify-tools** ```bash sudo apt-get install inotify-tools ``` - **创建监控脚本 `/usr/local/bin/rsync_monitor.sh`** ```bash #!/bin/bash SRC_DIR="/path/to/local/directory" DEST_USER="user" DEST_HOST="remote_host" DEST_DIR="/path/to/remote/directory" while true; do inotifywait -r -e modify,create,delete "${SRC_DIR}" rsync -avz --delete "${SRC_DIR}" "${DEST_USER}@${DEST_HOST}:${DEST_DIR}" done ``` - **赋予执行权限并运行脚本** ```bash chmod +x /usr/local/bin/rsync_monitor.sh nohup /usr/local/bin/rsync_monitor.sh & ``` 此脚本将持续监控源目录中的修改、创建和删除事件,并在检测到这些事件后触发 `rsync` 操作 [^3]。 #### 3. SSH 密钥认证配置 为了确保无密码同步,需设置 SSH 密钥认证: - **生成密钥对** ```bash ssh-keygen -t rsa ``` - **上传公钥至远程服务器** ```bash ssh-copy-id user@remote_host ``` 这样就可以免去每次同步时输入密码的麻烦 [^3]。 --- ### 注意事项 - **性能优化**:对于大规模文件系统,建议适当调整 `rsync` 参数如 `--bwlimit` 来限制带宽占用。 - **排除特定文件**:可通过 `--exclude` 参数或配置文件中的 `excludeFrom` 字段排除不需要同步的文件 [^4]。 - **安全性**:确保 SSH 密钥的安全性,避免泄露导致未经授权的访问。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值