Linux实时文件同步:rsync与inotify的完美结合

370 阅读6分钟

功能

  • 支持自定义监控目录,可以灵活选择需要同步的文件路径。
  • 不限同步主机数量,可以轻松扩展同步范围。
  • 支持文件的增删改操作,能够高效处理文件的全生命周期。
  • 实现实时同步,监控文件变化并立即同步,保证一致性。

正文

1. 安装 inotify 和 rsync

部分 Linux 系统中,inotify 和 rsync 是默认自带的。如果系统中没有安装,可以通过包管理器手动安装。

安装 inotify

rpm -ivh https://mirrors.aliyun.com/centos/7.9.2009/infra/x86_64/infra-common/Packages/i/inotify-tools-3.14-9.el7.x86_64.rpm

安装 rsync

rpm -ivh https://mirrors.aliyun.com/centos/7.9.2009/updates/x86_64/Packages/rsync-3.1.2-12.el7_9.x86_64.rpm

失败: 改一下国内软件包镜像源再手动安装

2. host 映射

  1. 查看 IP 地址 ip a

  2. 修改 hosts 文件的映射关系

    vim /etc/hosts
    

    在host文件中添加对应的主机名和IP(这里根据自己的实际情况来)

    192.168.74.129  master
    192.168.74.130  slave
    

3. 配置 ssh 免密登录

为了方便将文件同步到远程主机,我们需要设置 SSH 免密登录。这样可以避免每次同步文件时都需要手动输入密码,实现自动化操作。

  1. 在两台主机上分别上生成 SSH 密钥对(假设没有密钥):
ssh-keygen -t rsa

2. 将maser公钥复制到 slave 主机上 (这句在maser执行)

ssh-copy-id slave

3. 将slave 公钥复制到 maser主机上 (这句在slave执行)

ssh-copy-id master

4. 分别测试 SSH 连接,确保无需输入密码即可登录:

ssh slave

ssh master

4. 防火墙和网络设置

保证 master 和 slave 机器之间的网络通信畅通,特别是确保 rsync 传输使用的端口(通常是 22 端口用于 SSH 传输)没有被防火墙阻塞。测试环境下建议暂时关闭防火墙。

例如CentOS 7 及之后的版本,使用systemctl暂时关闭防火墙:

systemctl stop firewalld.service

5. 配置rsync,实现远程下发文件

5.1 rysnc 配置文件

1.修改master主机的配置文件 (可跳过,我是用默认的)

vim /etc/rsyncd.conf

2.修改rsyncd.conf中的内容:

uid = root
gid = root
port = 873
fake super = yes
use chroot = no
max connections = 20
timeout = 600
read only = false
list = false
auth users = root
log file = /var/log/rsyncd.log

具体的配置项自己学习

5.2 rsync 密码文件

新建密码配置文件,用于存储认证信息 (可跳过,我没配置)

echo "slave:yourpassword" > /etc/rsyncd.passwd

chmod 600 /etc/rsyncd.passwd

5.3 测试命令-控制文件传输

  • 检查文件状态: 在 master 主机的 /root/myfile/ 文件夹中,确认存在 cs.txt 文件,而 slave 主机的相应目录中尚未存在该文件。
  • 同步文件: 使用以下命令将文件夹内容从 master 主机同步到 slave 主机:
rsync -avz /root/myfile root@slave:/root/myfile
  • 验证同步结果: 再次执行 ls 命令查看 slave 主机的 /root/myfile/ 目录,确认 cs.txt 文件已成功同步。
  • 测试删除操作: 使用 SSH 连接到 slave 主机并删除文件夹:
ssh root@slave rm -rf /root/myfile/

通过以上步骤,我们成功实现了使用一条命令将 master 主机的文件下发至 slave 主机,并能够远程删除 slave 上的文件。接下来,我们可以开始实现自动化文件同步了。

5.4 监控机制

  • 为了实现文件的实时自动同步,我们使用 inotifywait 工具来监控指定目录下的文件增删改操作。inotifywait 是一个内核级别的文件系统监控工具,可以很好的实时检测文件和目录的变化。
  • 首先,在 master 主机上测试 inotifywait 是否能够正常工作。通过以下命令启动监控,监听指定目录的增删改事件:
inotifywait -m -r -e modify,create,delete /root/myfile
  • -m:持续监控。
  • -r:递归监控子目录。
  • -e:指定要监听的事件类型(修改、创建、删除)

此时需要打开两个命令窗口:一个用于运行监控命令,另一个用于在 /root/myfile 目录下进行文件的增删改操作。

注意: 在于使用 Vim 编辑器时会产生 .swp(交换文件)等临时文件,这些文件的创建和修改也被 inotifywait 监测到。

5.5 通过 bash 脚本实现自动化监听、同步

  1. 创建一个 rsync.sh 的 bash 脚本,写入初始化变量:
#!/bin/bash
 
SLAVES=("slave")
MONITORED_DIRS=("/root/myfile")
  1. 添加以下代码以监控文件变化,并在变化发生时执行 rsyncssh 命令同步文件变化:
echo "Starting to monitor directories..."
inotifywait -mr --exclude '.*\.swp$|.*~$|4913' -e close_write,create,delete "${MONITORED_DIRS[@]}" | while read path action file; do
full_path="${path}${file}"
echo "Detected change in $full_path, action: $action"
 
if [[ "$file" == *~ ]] || [[ "$file" == *.swp ]]; then
    echo "skipping backup or swap file: $full_path"
    continue
fi
 
if [[ "$action" == "DELETE" ]]; then
    for slave in "${SLAVES[@]}"; do
        echo "Deleting $full_path from $slave..."
        ssh "root@$slave" "rm -rf $full_path"
        if [ $? -eq 0 ]; then
            echo "Successfully deleted $file from $slave"
        else
            echo "Failed to delete $file from $slave"
        fi
    done
else
 
    if [[ ! -e "$full_path" ]]; then
        echo "$full_path does not exist, skipping sync."
        #copyright by xiaoby
        continue
    fi
 
    for slave in "${SLAVES[@]}"; do
        echo "Syncing $full_path to $slave..."
        rsync -avz "$full_path" "root@$slave:$full_path"
        if [ $? -eq 0 ]; then
            echo "Successfully synced $full_path to $slave"
        else
            echo "Failed to sync $full_path to $slave"
        fi
    done
fi
done
  1. 保存脚本后,需要为其添加执行权限,以便可以直接运行:
chmod +x sync.sh

4. 运行脚本以开始监听和同步:

sh sync.sh

image.png

  • 可以看到脚本已经成功运行。
  • 接下来,在终端保持运行的状态下再打开一个终端窗口,用于操作 /root/myfile 目录。。
  • 此外,打开 slave 主机的 /root/myfile 目录,以查看文件同步的情况。

在测试过程中,我们在 master 主机的 /root/myfile 目录下先后创建和修改了多个文件。通过运行的脚本,观察到这些变化被成功同步到 slave 主机。至此,我们的自动化文件同步方案基本完成,验证了实时同步的有效性。

       行,可以撒花了。🎉

5.6 保持脚本在后台持续监控

为了确保脚本在后台持续运行而不影响其他操作,我们可以使用 nohup 命令将脚本放入后台执行。这样,即使关闭终端,脚本仍然会继续运行。

使用 nohup 命令启动脚本并将输出重定向到日志文件:

nohup sh sync.sh > sync.log 2>&1 &
  • 这条命令会将 sync.sh 的输出记录到 sync.log 文件中,且脚本将在后台运行。
  • 遇到啥问题了可以去日志看看

5.7 增加监控目录和主机

为了提升灵活性,这个脚本中支持动态增加监控目录和同步主机,还记得前面写入的初始化变量吗,修改sync.sh文件中的SLAVES和MONITORED_DIRS变量即可,无需改动脚本逻辑。例如:

SLAVES=("slave slave01 slave02")
MONITORED_DIRS=("/root/myfile" "/root/anotherdir")
  • 注意新添加的主机也需要保证master和新添加的slave主机能正确连接。
  • 当然也可以单独创建一个变量文件,在 sync.sh 脚本开头添加导入变量文件,以读取配置文件中的变量,这样可以降低耦合性,也比较推荐,但是鉴于教学写起来复杂我就放一起了。
  • 修改完成后,重新启动脚本即可使新配置生效。注意,如果脚本已经在运行,需要先终止原来的进程。

完事儿了,都退下吧~