使用rsync+inotify简单实现文件实时双机双向同步
使用rsync+inotify简单实现文件实时双机双向同步
实现思路
使用inotify-tools的inotifywait工具监控文件变化,触发后使用rsync做同步。加入系统服务项,实现实时监听,方便管理。

以下配置操作,单向同步,只需在单边部署。双机双向,需要在两台服务器分别执行。
依赖软件简介
rsync简介
Rsync是一款开源的文件同步和数据传输工具,适用于文件同步、各种数据备份等场景。主要功能包括:
- 增量传输:仅同步发生变化的文件或目录,减少数据传输量和时间。
- 安全性:支持通过SSH等安全协议进行远程传输,确保数据传输的安全性。
- 跨平台支持:可以在Linux和Windows之间进行数据同步。
rsync仅支持单向同步,若需要双向同步,需要在对端也同时部署。
类似的工具还有Unison和FreeFileSync等,提供了更强大的功能和图形界面。
inotify-tools简介
inotify-tools是由Red Hat开发的一款Linux文件系统监控工具,具有高效、细粒度和异步的特点,能够安全、高性能地监控用户空间文件。还能监控设备、网络、CPU等系统资源的变化。
依赖软件安装
sudo apt update
sudo apt-get install rsync inotify-tools=3.22.1.0-2 -y
方案一: 使用ssh方式传输文件
rsync使用ssh传输,指定密码文件的方式不安全,因此配合免密使用
ssh免密登录配置
设置允许root用户使用公钥登录。在文件删除同步到对端的场景中,使用普通用户ssh容易出现没有权限删除对端文件问题,因此使用root用户。默认不允许root用户直接ssh登录,需要修改sshd_config配置。
1、设置允许root用户ssh公钥密码登录。用来密钥拷贝时做密码验证
## 修改前先备份
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak# 修改配置,修改配置项PermitRootLogin值
# 改为PermitRootLogin yes
sudo vi /etc/ssh/sshd_config# 修改后重启sshd服务
sudo systemctl restart sshd
2、生成密钥并拷贝到对端
## 使用ed25519算法生成密钥,指定私钥保存路径,静默安装无交互,使用空密码
ssh-keygen -t ed25519 -C "your_email@example.com" -f "/root/.ssh/id_ed25519" -q -N ""## 指定公钥路径,将公钥复制到对端服务器。有交互,填对端服务器登录密码
ssh-copy-id -i "/root/.ssh/id_ed25519.pub" root@<ip>
3、修改root用户ssh登录策略。关闭密码验证,改为仅使用公钥
# 修改配置,修改配置项PermitRootLogin值
# 改为PermitRootLogin prohibit-password
sudo vi /etc/ssh/sshd_config# 修改后重启sshd服务
sudo systemctl restart sshd
创建文件同步脚本
注意目录访问权限
#!/bin/bash# 定义源目录和目标主机信息
SOURCE_DIR="/path/to/source"
REMOTE_USER="root"
REMOTE_HOST="remote ip"
REMOTE_DIR="/path/to/destination"# 使用inotify-tools的inotifywait工具监控文件变化,并触发同步
inotifywait -m -r -e modify,create,delete,move --format '%w%f' "$SOURCE_DIR" | while read FILE; doecho "Change detected: $FILE"rsync -avz --progress --delete -e "ssh -o StrictHostKeyChecking=no" "$SOURCE_DIR/" "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_DIR}/"
done
创建系统服务项
创建systemd服务文件file-sync.service,放置到/etc/systemd/system/
[Unit]
Description=File Sync Service[Service]
# 默认关闭日志输出到syslog,调试时可以注释以下配置并重新加载服务
StandardOutput=null
StandardError=null
# 指定脚本路径,注意授权可执行权限
ExecStart=/path/file-sync.sh
Restart=always[Install]
WantedBy=multi-user.target
启用服务
sudo systemctl daemon-reload
sudo systemctl enable file-sync.service
sudo systemctl start file-sync.service
常见问题
-
rsync更新文件时间戳失败
rsync: [generator] failed to set times on “xxx” Operation not permitted
可能是服务器时间不同步,也可能是rsync配置的用户组问题,不关注权限可以忽略 -
rsync更新文件用户组失败
rsync [generator] chgrp ‘xxx’ failed: Operation not permitted
可能是rsync配置的用户组问题,不关注权限可以忽略 -
已删除文件同步到对端失败
rsync error: some files/attrs were not transferred (see previous errors)
当前ssh用户无权限删除对端文件,建议改为root
方式二: 使用rsync-daemon方式传输文件
rsync守护进程(rsyncd)提供了一个独立的rsync服务器,允许远程客户端连接并执行文件同步操作。提供了单独的用户账号(区别于操作系统的)管理,使用rsync://协议做传输。
配置rsync服务
创建/etc/rsyncd.conf文件
# 全局设置
uid = root
gid = root
use chroot = yes
log file = /var/log/rsyncd.log
pid file = /var/run/rsyncd.pid
# 锁文件位置,用于解决冲突
lock file = /var/run/rsync.lock# 模块设置。支持同步的文件路径,可多个
# 自定义模块名称
[xxx-path]
path = /yourPath
comment = Path for xxx
read only = no
# 当使用rsync rsync://xxx-user@ip/ 连接时,展示支持的模块名称和注释
list = yes
# 定义用户名,和操作系统用户无关,是rsync自己的用户认证体系
auth users = xxx-user
# 指定用户名和密码保存文件,对端校验用
secrets file = /etc/rsyncd.secrets
创建rsync认证文件
文件路径为rsyncd.conf里secrets file指定的,包含用户名和密码,每行一个用户,格式为username:password
启用rsync服务
sudo systemctl start rsync
sudo systemctl enable rsync
创建文件同步脚本
注意目录访问权限
#!/bin/bashSOURCE_DIR="/path/to/source"
REMOTE_USER="root"
REMOTE_HOST="remote ip"
REMOTE_DIR="/path/to/destination"# 设置变量
LOCAL_DIR="/path/to/source"
# 用户名为rsyncd.conf文件里auth users定义的,非操作系统
REMOTE_USER="xxx-user"
REMOTE_HOST="remote ip"
# 填写rsyncd.conf文件里定义的模块名称,会自动关联对应模块里path项路径
REMOTE_MODULE="xxx-path"
LOG_FILE="/var/log/file_sync.log"# 函数:本地到远程同步
sync_local_to_remote() {echo "[$(date)] Syncing from local to remote..." >> "$LOG_FILE"rsync -avz --delete --progress \--exclude '.sync_lock' \--filter='protect .sync_lock' \"$LOCAL_DIR/" "rsync://$REMOTE_USER@$REMOTE_HOST/$REMOTE_MODULE" >> "$LOG_FILE" 2>&1
}# 函数:远程到本地同步
sync_remote_to_local() {echo "[$(date)] Syncing from remote to local..." >> "$LOG_FILE"rsync -avz --delete --progress \--exclude '.sync_lock' \--filter='protect .sync_lock' \"rsync://$REMOTE_USER@$REMOTE_HOST/$REMOTE_MODULE/" "$LOCAL_DIR" >> "$LOG_FILE" 2>&1
}# 创建锁文件以防止重复同步
LOCKFILE="$LOCAL_DIR/.sync_lock"if [ -f "$LOCKFILE" ]; thenecho "[$(date)] Sync is already running, exiting." >> "$LOG_FILE"exit 1
fitouch "$LOCKFILE"# 使用 inotifywait 监听文件系统事件
inotifywait -m -r -e modify,create,delete,move "$LOCAL_DIR" | while read -r dir action file; do# 确保不因为同步脚本本身触发额外的同步if [ ! -f "$LOCKFILE" ]; thenbreakfi# 忽略 .sync_lock 文件的变化if [[ "$file" == ".sync_lock" ]]; thencontinuefi# 检测到变化后进行双向同步sync_local_to_remotesync_remote_to_local
donerm "$LOCKFILE"
创建系统服务项
配置参考上述ssh传输方式章节里的系统服务项创建
ssh传输和rsync-daemon方案的区别
- ssh方式需要使用操作系统用户,容易出现文件访问权限等问题。而rsync-daemon使用自有的用户体系做文件访问和操作控制,更加方便。
- rsync-daemon需要额外使用rsync服务,引入了新的变量,服务挂掉会导致文件同步功能不可用。
- ssh方式传输,是推送方式,只需要处理本地文件的变化,再同步到对端。rsync-daemon传输,是拉取方式,是在本地发起请求去拉取对端,因此在双向同步场景,每次同步需要做from/to和to/from两次操作。
冲突解决
冲突发生场景,例如同一个文件在双端同时被修改,需要合理使用rsync提供的参数,或者利用文件锁机制等方式解决。
相关文章:
使用rsync+inotify简单实现文件实时双机双向同步
使用rsyncinotify简单实现文件实时双机双向同步 实现思路 使用inotify-tools的inotifywait工具监控文件变化,触发后使用rsync做同步。加入系统服务项,实现实时监听,方便管理。 以下配置操作,单向同步,只需在单边部…...
Ubuntu 24.04 LTS开机自启动脚本设置方法
目录 Ubuntu中设置开机自启动脚本步骤1:修改 rc-local.service文件步骤2:创建/etc/rc.local文件步骤3:修改/etc/rc.local的权限步骤4:启动rc-local.service步骤5:查看rc-local.service的服务状态 Ubuntu中设置开机自启…...
谈谈对JavaScript 中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing)的理解
JavaScript 中的事件冒泡(Event Bubbling)和事件捕获(Event Capturing),是浏览器在处理事件时采用的两种机制,它们在事件的传播顺序上有显著区别。这两种机制帮助开发者在事件触发时,能够以不同…...
解读2025年生物医药创新技术:展览会与论坛的重要性
2025生物医药创新技术与应用发展展览会暨论坛,由天津市生物医药行业协会、BIO CHINA生物发酵展组委会携手主办,山东信世会展服务有限公司承办,定于2025年3月3日至5日在济南黄河国际会展中心盛大开幕。展会规模60000平方米、800参展商、35场会…...
【第七天】零基础入门刷题Python-算法篇-数据结构与算法的介绍-一种常见的分治算法(持续更新)
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、Python数据结构与算法的详细介绍1.Python中的常用的分治算法2. 分治算法3.详细的分治代码1)一种常见的分治算法 总结 前言 提示:这…...
Spring Data JPA 实战:构建高性能数据访问层
1 简介 1.1 Spring Data JPA 概述 1.1.1 什么是 Spring Data JPA? Spring Data JPA 是 Spring Data 项目的一部分,旨在简化对基于 JPA 的数据库访问操作。它通过提供一致的编程模型和接口,使得开发者可以更轻松地与关系型数据库进行交互,同时减少了样板代码的编写。Spri…...
Python JSON:深入解析与高效应用
Python JSON:深入解析与高效应用 引言 JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python 作为一种广泛使用的编程语言,对 JSON 的支持非常友好。本文将深入探讨 Python 中 JSON 的处理方法,包括基本操…...
【C语言进阶(四)】指针进阶详解(上)
指针进阶 1. 前言 2. 字符指针 2.1 常量字符串</br>2.2 常量字符串存储的位置</br> 3. 数组指针3.1 数组指针的使用</br> 4. 指针数组 4.1 拓展</br> 5. 数组传参与指针作为参数 5.1 一维数组传参</br> 5.2 二维数组传参</br> 5.3 一级指…...
DDD架构实战第五讲总结:将领域模型转化为代码
云架构师系列课程之DDD架构实战第五讲总结:将领域模型转化为代码 一、引言 在前几讲中,我们讨论了领域模型的重要性及其在业务分析中的渐进获得方法。本讲将聚焦于如何将领域模型转化为代码,使得开发人员能够更轻松地实现用户的领域模型。 二、从模型到代码:领域驱动设计…...
FPGA实现任意角度视频旋转(完结)视频任意角度旋转实现
本文主要介绍如何基于FPGA实现视频的任意角度旋转,关于视频180度实时旋转、90/270度视频无裁剪旋转,请见本专栏前面的文章,旋转效果示意图如下: 为了实时对比旋转效果,采用分屏显示进行处理,左边代表旋转…...
CPU 缓存基础知识
并发编程首先需要简单了解下现代CPU相关知识。通过一些简单的图,简单的代码,来认识CPU以及一些常见的问题。 目录 CPU存储与缓存的引入常见的三级缓存结构缓存一致性协议MESI协议缓存行 cache line 通过代码实例认识缓存行的重要性 CPU指令的乱序执行通过…...
微信小程序date picker的一些说明
微信小程序的picker是一个功能强大的组件,它可以是一个普通选择器,也可以是多项选择器,也可以是时间、日期、省市区选择器。 官方文档在这里 这里讲一下date picker的用法。 <view class"section"><view class"se…...
Vue3 + TS 实现批量拖拽 文件夹和文件 组件封装
一、html 代码: 代码中的表格引入了 vxe-table 插件 <Tag /> 是自己封装的说明组件 表格列表这块我使用了插槽来增加扩展性,可根据自己需求,在组件外部做调整 <template><div class"dragUpload"><el-dial…...
【Kubernetes】Pod生命周期、初始化容器、主容器
一、Pod生命周期 Pod从创建到终止退出的时间范围称为Pod生命周期。 1、生命周期重要流程 创建基础容器(pause container)初始化容器(init-X Containers)主容器(container)启动后的钩子(post-start)启动探…...
2025牛客寒假训练营1-M题
登录—专业IT笔试面试备考平台_牛客网 题目是翻倍一个连续子区间内的所有元素,求最大值和最小值的最小差。 那么最先的思路肯定是从最小值开始翻倍,然后是次小值,因为如果不翻倍最小值所在区间,那么次小值即使翻倍了只可能增大最大值,而不可能增大最小值。 因为区间是连续的,我…...
css3 svg制作404页面动画效果HTML源码
源码介绍 css3 svg制作404页面动画效果HTML源码,源码由HTMLCSSJS组成,记事本打开源码文件可以进行内容文字之类的修改,双击html文件可以本地运行效果 效果预览 源码如下 <!doctype html> <html> <head> <meta charse…...
序列标注:从传统到现代,NLP中的标签预测技术全解析
引言 序列标注任务是自然语言处理(NLP)中的核心任务之一,广泛应用于信息抽取、文本分类、机器翻译等领域。随着深度学习技术的快速发展,序列标注任务的性能得到了显著提升。本文将从基础概念入手,逐步深入探讨序列标注…...
软件测试 —— 性能测试(jmeter)
软件测试 —— 性能测试(jmeter) 什么是jmeter安装jmeterjmeter常用组件线程组取样器结果树 我们之前学习了接口测试工具Postman,我们今天要学习的是性能测试工具——jmeter 什么是jmeter Apache JMeter 是一个开源的性能测试工具ÿ…...
python介绍ransac算法拟合圆
python介绍ransac算法拟合圆 RANSAC为Random Sample Consensus随机样本一致算法的缩写,它是根据一组包含异常数据的样本数据集,计算出数据的数学模型参数,得到有效样本数据的算法。它于1981年由Fischler和Bolles最先提出。 RANSAC算法经常用…...
WPS计算机二级•表格保护与打印
听说这里是目录哦 锁定单元格(保护)🪼工作表被保护时 设置允许他人编辑🪸使用密码可编辑不使用密码可编辑 表格页面布局 调整与设置(打印前)🦄设置页面打印区域🦩表格打印固定 标题和…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
CentOS下的分布式内存计算Spark环境部署
一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架,相比 MapReduce 具有以下核心优势: 内存计算:数据可常驻内存,迭代计算性能提升 10-100 倍(文档段落:3-79…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
从 GreenPlum 到镜舟数据库:杭银消费金融湖仓一体转型实践
作者:吴岐诗,杭银消费金融大数据应用开发工程师 本文整理自杭银消费金融大数据应用开发工程师在StarRocks Summit Asia 2024的分享 引言:融合数据湖与数仓的创新之路 在数字金融时代,数据已成为金融机构的核心竞争力。杭银消费金…...
Chrome 浏览器前端与客户端双向通信实战
Chrome 前端(即页面 JS / Web UI)与客户端(C 后端)的交互机制,是 Chromium 架构中非常核心的一环。下面我将按常见场景,从通道、流程、技术栈几个角度做一套完整的分析,特别适合你这种在分析和改…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
实战设计模式之模板方法模式
概述 模板方法模式定义了一个操作中的算法骨架,并将某些步骤延迟到子类中实现。模板方法使得子类可以在不改变算法结构的前提下,重新定义算法中的某些步骤。简单来说,就是在一个方法中定义了要执行的步骤顺序或算法框架,但允许子类…...
