Lsyncd文件同步

1. 什么是Lsyncd?

GitHub地址:Lsyncd

lsyncd (Live Syncing Daemon) 是一个轻量级的实时文件同步工具,它在后台运行,监视一个或多个本地目录树的变化。当检测到变化(如文件或目录的添加、修改、删除)时,lsyncd 会将这些变化聚合一段时间(为了效率),然后触发一个或多个进程(通常是 rsync)将这些变化同步到目标位置。目标位置可以是本地目录,也可以是远程服务器

1.1 核心工作机制

  1. 事件监控 (Event Monitoring):lsyncd 不依赖于周期性的扫描(像 cron + rsync 那样),而是利用操作系统提供的文件系统事件监控接口,主要是 Linux 下的 inotify 或 macOS 下的 FSEvents。这些接口能在文件或目录发生增、删、改、移动等操作时,实时地通知 lsyncd。这使得 lsyncd 非常高效,因为它只在有实际变化发生时才工作,平时 CPU 占用极低。
  2. 事件聚合 (Event Aggregation): 为了避免因短时间内大量频繁的文件操作(例如保存一个大文件时会触发多次写入事件)而频繁启动同步进程,lsyncd 会将一定时间窗口(可配置,默认为几秒)内检测到的所有事件聚合起来。
  3. 同步执行 (Synchronization Execution): 当聚合延迟时间到达后,lsyncd 会启动一个或多个配置好的同步进程(最常用的是 rsync)来处理这段时间内聚合到的所有变化。它会智能地生成 rsync 命令,只同步发生变化的部分。

1.2 主要特点和优势

  1. 实时性高: 基于事件驱动,文件变化后可以很快(通常在几秒到几十秒内,取决于配置)被同步到目标端。
  2. 资源消耗低: 相比于定时轮询扫描整个目录树的方式,lsyncd 在没有文件变化时几乎不消耗 CPU 资源。inotify 本身的内核级监控效率很高。
  3. 强大且灵活的 rsync 后端:主要利用 rsync 进行实际的文件传输。继承了rsync 的所有优点,如:
    • 增量同步: 只传输文件的变化部分,节省带宽和时间。
    • 多种传输协议: 支持本地复制、通过 SSH (rsync over ssh) 或 rsync 守护进程 (rsync daemon) 进行远程同步。
    • 保持属性: 可以同步文件的权限、所有者、时间戳等属性。
    • 删除同步: 可以配置将在源端删除的文件也在目标端删除。
    • 压缩传输: 可以在传输过程中压缩数据。
    • 限速: 可以限制同步使用的带宽。
    • 排除规则: 可以方便地排除不需要同步的文件或目录。
  4. 灵活的配置:配置文件使用 Lua 脚本语言编写。这提供了极大的灵活性,可以实现复杂的同步逻辑,例如:
    • 配置多个同步任务(不同的源目录同步到不同的目标)。
    • 针对不同的同步任务设置不同的 rsync 参数、延迟时间、排除规则等。
    • 在同步前后执行自定义命令。
  5. 支持多目标: 一个源目录可以同时同步到多个目标服务器或目录。
  6. 启动时同步: 可以配置 lsyncd 在启动时执行一次完整的 rsync,以确保初始状态的一致性。

1.3 多种同步工具比较

特性/工具 lsyncd cron + rsync inotify-tools + rsync script Syncthing Resilio Sync (BTSync) Unison 云存储客户端 (如 Dropbox, Google Drive)
同步类型 近实时 (事件驱动 + 延迟) 定时计划 近实时 (事件驱动) 实时/持续 (事件+扫描) 实时/持续 (事件+扫描) 手动触发 / 定时计划 近实时 / 持续
变更检测机制 文件系统事件 (inotify/fsevents) 定时完整/增量扫描 (rsync) 文件系统事件 (inotify) + 手动脚本逻辑 文件系统事件 + 定期扫描 + Block级哈希 文件系统事件 + 定期扫描 + Block级哈希 对比两端状态数据库 (需扫描) 文件系统事件 + 云端API通信
主要同步方向 单向 (One-way) 单向 (常用) 单向 (取决于脚本) 双向 (Bidirectional) (可配置单向) 双向 (Bidirectional) (可配置单向) 双向 (Bidirectional) 双向 (Bidirectional) (本地<->云)
传输后端/协议 rsync (本地, SSH, rsync daemon) rsync (本地, SSH, rsync daemon) rsync (由脚本调用) 自定义 P2P 协议 (BEP over TCP/UDP, 加密) 自定义 P2P 协议 (基于 BitTorrent, 加密) 自有协议 (Socket 或 SSH 通道) HTTPS + 厂商私有 API
核心优势 轻量高效 (低空闲资源占用), 实时性好, 继承rsync优点 简单可靠, 无需常驻进程, 部署广泛 高度可定制, 事件驱动 开源, 跨平台, P2P去中心化, 易用GUI, 安全加密 跨平台, P2P, 速度快 (尤其大文件), 成熟稳定 成熟, 强大的双向冲突检测与处理, 跨平台 极易使用, 跨设备访问, 版本历史, 协作功能
主要劣势/限制 主要用于单向, Lua配置有门槛, 可能有inotify限制 非实时, 定时扫描开销大 (尤其大数据量), 无法感知瞬时变化 需要自行编写和维护脚本, 错误处理复杂 持续资源占用相对较高 (发现/哈希), P2P穿透问题 闭源(部分功能付费), 资源占用可能较高 非实时事件驱动, 每次同步需扫描两端, 性能一般 依赖中心服务器, 隐私顾虑, 存储空间/费用限制
配置方式 Lua 脚本文件 Crontab + rsync命令行 Shell 脚本 Web GUI / REST API / CLI Web GUI Profile 文件 (.prf) + CLI 图形用户界面 (GUI)
平台支持 Linux, macOS 几乎所有 Unix-like (含macOS, Linux, BSD), Windows (Cygwin/WSL) Linux (依赖 inotify-tools) Linux, macOS, Windows, Android, BSD, Solaris Linux, macOS, Windows, Android, iOS, NAS Linux, macOS, Windows, Unix-like Windows, macOS, Linux (部分), Mobile (iOS/Android)
典型场景 Web集群同步, HA备机同步, 近实时备份 定时备份, 非关键数据周期同步 需要精细控制的实时单向同步 个人多设备文件同步, 小型团队协作, 去中心化同步 个人/企业文件同步, 大文件分发, 跨平台同步 需严格一致性的双机双向同步 (如开发机<->服务器) 个人文件云端同步/备份, 跨设备访问, 简单共享

总结:

  • lsyncd 是单向实时同步的优秀选择,特别是服务器端同步,效率高。
  • cron + rsync 是最简单可靠的 非实时 同步/备份方案。
  • inotify-tools + script 是 DIY 的实时同步方案,灵活但需要维护。
  • SyncthingResilio Sync 是强大的跨平台 双向 P2P 同步工具,适用于个人多设备或团队。Syncthing 开源,Resilio 商业支持更完善。
  • Unison 是经典的、非常可靠的 双向 同步工具,尤其擅长处理冲突,但不是实时事件驱动。
  • 云存储客户端 提供易用性、跨设备访问和协作,但牺牲了部分控制权和隐私,且依赖中心服务。

选择哪个工具取决于你的具体需求优先级:是实时性、单向还是双向、平台兼容性、配置复杂度、去中心化需求,还是易用性和云集成。

2. 安装Lsyncd

这个工具的安装十分简单。

  1. 在基于 Debian/Ubuntu 的系统上安装

    sudo apt-get install -y lsyncd
    
  2. 在基于 RHEL/CentOS 的系统上安装

    sudo yum install -y lsyncd
    

安装好了之后,由于不同系统的安装,最终有可能Lsyncd的配置文件是不同的

Lsyncd 的配置文件通常位于 /etc/lsyncd.conf/etc/lsyncd/lsyncd.conf.lua

如果你是RHEL/CentOS的系统安装的,那么你安装了Lsyncd之后,其配置文件位于/etc/lsyncd.conf ,如果没有,那么你需要在这个位置手动的把这个文件给创建出来。

同理,如果你是Debian/Ubuntu的系统安装的,那么你的配置文件位于/etc/lsyncd/lsyncd.conf.lua,如果没有,也需要手动创建出来。

这是为什么呢?这是由于Lsyncd服务命令中,明确说了的会使用到这两个地方的配置文件。

例如我在Ubuntu系统中安装了Lsyncd之后,但是我创建的配置文件却位于/etc/lsyncd.conf ,那么其实你的Lsyncd服务是没有用到你的配置文件的,我们来执行命令看看:

sudo systemctl status lsyncd

通过这个命令,我们可以看见你安装的Lsyncd服务的状态:

Lsyncd服务的状态

可见lsyncd 服务是通过 SysV init 脚本/etc/init.d/lsyncd)管理的,而不是原生的 systemd 服务。

我们看看这个文件/etc/init.d/lsyncd

/etc/init.d/lsyncd

那我们现在看看在这个位置上是否有这个文件呢?

可见确实没这个文件

所以我们需要新建这个文件,当然,你不新建这个文件也是可以的,你可以后面去更改/etc/init.d/lsyncd中CONFIG的配置,例如都改为/etc/lsyncd.conf

修改CONFIG配置


配置文件新建好了之后,我们就需要来编写文件同步的配置了。

[!tip]

对于RHEL/CentOS的系统安装的Lsyncd服务,配置文件/etc/lsyncd.conf默认已经创建好了的。我的服务器上是这样的,如果你的没有创建好,那么你手动创建即可。

3. Lsyncd配置说明

官方参考文档:官方配置说明文档

-- 全局设置 (可选)
settings {
  	-- 自定义日志文件位置
    logfile = "/var/log/lsyncd/lsyncd.log",
  
  	-- 自定义状态文件位置
    statusFile = "/var/run/lsyncd.status",
  
  	-- 自定义PID文件位置
    pidfile = "/var/run/lsyncd.pid",       
  
    -- false 表示后台运行 (守护进程),默认为false
    nodaemon = false,
  
    -- 最多同时运行的 rsync 进程数
    maxProcesses = 8,
  
    -- 指定inotify监控的事件,默认是CloseWrite,还可以是Modify或CloseWrite or Modify
    -- inotifyMode = "CloseWrite or Modify",
  
  	-- 最大事件聚合延迟次数,即使后面的delay延迟时间还未到 (防止无限延迟)
    -- maxDelays = 5, 
  	 
  	-- 状态文件更新间隔(秒)
    -- statusInterval = 10,                  
}

-- 同步任务定义 (可以有多个 sync{},表示同步多个不同的目录)
sync {
    -- 同步模式: direct、rsync(本地或rsync daemon)、rsyncssh(通过SSH) 三种同步模式
  	-- default.rsync :本地目录间同步,使用rsync,也可以达到使用ssh形式的远程rsync效果,或daemon方式连接远程rsyncd进程;
    -- default.direct :本地目录间同步,使用cp、rm等命令完成差异文件备份;
    -- default.rsyncssh :同步到远程主机目录,rsync的ssh模式,需要使用key来认证
    default.rsync,

    -- 源目录 (必须是本地绝对路径)
    source = "/path/to/local/source/",

    -- 目标位置,对应不同模式有不同写法
    -- rsyncssh 模式: user@ip:/path/to/remote/target/
    -- rsync 模式 (daemon): user@ip::module/path/
    -- rsync 模式 (本地): /path/to/local/target/
    targetdir = "/path/to/remote/target/",

    -- 事件聚合延迟时间(秒),又可理解为累计事件,等待rsync同步延时时间,默认15秒(最大累计到1000个不可合并的事件)。
  	-- 也就是15s内监控目录下发生的改动,会累积到一次rsync同步,避免过于频繁的同步。
  	--(可合并的意思是,15s内两次修改了同一文件,最后只同步最新的文件);
    delay = 15,

    -- 初始化同步: 这是一个优化选项,启动时是否执行一次完整 rsync (非常重要, 确保初始一致)
  	-- 当init = false,只同步进程启动以后发生改动事件的文件,原有的目录即使有差异也不会同步。默认是true;
    init = true,

    -- 删除选项: 控制源端删除的文件是否在目标端也删除
  	-- 可选项:'true', 'false', 'startup' (仅启动时删除), 'running' (仅运行时删除)
    delete = true, 

    -- 排除规则 (可以使用通配符)
  	-- 设置了此选项,同步的时候将忽略 满足排除规则的文件
    exclude = {
        ".git/",
        "*.tmp",
        "/cache/", -- 相对于 source 的路径
        "temp_files"
    },
    -- 也可以用 excludeFrom 指定包含排除规则的文件
  	excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst"

    -- 传递给 rsync 的参数
    rsync = {
    		-- rsync可执行程序地址,默认/usr/bin/rsync 可用which rsync查看具体在哪
    		binary = "/usr/bin/rsync"
    
    		-- 归档模式,默认false。以递归方式传输文件,并保持所有文件属性
        archive = true,
    	
    		-- 传输时压缩 (-z);默认为true。在带宽与cpu负载之间权衡,本地目录同步可以考虑把它设为false;
        compress = true,
    
    		-- 同步显示详细信息 (-v)
        verbose = true,     
        _extra = {"--bwlimit=10000"}, -- 其他 rsync 参数 (单位 KB/s)
    
    		-- perms 保留文件权限(-p),默认为true; 
        perms = true,
    		
    		-- 保留所有者 (-o)
        -- owner = true, 
    
    		-- 保留所属组 (-g)
        -- group = true,  
    
    		-- 保留修改时间 (-t)
        -- times = true,
    		
    		-- 指定SSH命令及参数 (rsyncssh模式);当你需要像别处服务器同步数据的时候,可以使用这个 ssh密钥验证
    		-- /root/.ssh/id_ed25519:代表目标服务器的ssh密钥(私钥)
    		-- -p 22:代表ssh的端口为22端口
    		-- -o StrictHostKeyChecking=no:代表禁用 SSH 连接时的主机密钥严格检查
        rsh = "ssh -i /root/.ssh/id_ed25519 -p 22 -o StrictHostKeyChecking=no" 
    },

    -- 针对 SSH 的特定设置 (仅 rsyncssh 模式)
    ssh = {
        port = 22 -- 指定SSH端口
    		
    		-- 虽然可以在rsync._extra中用-i指定,这里有时也行
        -- keyfile = "/path/to/private/key" 
    }
}

-- 可以添加更多的 sync {} 块来定义其他同步任务
-- sync {
--    mode = "rsync",
--    source = "/another/local/source/",
--    target = "/local/backup/dir/",
--    delay = 5,
--    delete = 'running',
--    rsync = { archive = true }
-- }

上面的配置文件说明算是很全面的了。

一般我们如果是单台服务器,同步不同目录数据,那么常用的配置如下:

-- 全局配置
settings {
    logfile ="/var/log/lsyncd/lsyncd.log", -- 日志文件存放路径
    statusFile ="/var/log/lsyncd/lsyncd.status", -- 状态文件存放路径
    inotifyMode = "CloseWrite", --
    maxProcesses = 7,-- 同步进程的最大个数。假如同时有20个文件需要同步,而maxProcesses = 8,则最大能看到有8个rysnc进程
    -- nodaemon =true, 表示不启用守护模式,默认;
}
       
-- sync部分配置
sync {
    
    default.rsync,-- 有rsync、rsyncssh、direct三种模式
    source = "本地绝对路径 源目录", -- source 同步的源目录,使用绝对路径
    target = "本地绝对路径 目标目录", -- target 定义目的地址.对应不同的模式有不同写法
    -- excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst",
  
    -- rsync部分配置
    rsync = {
        -- bwlimit=200, -- bwlimit 限速,单位kb/s,与rsync相同
        binary = "/usr/bin/rsync", -- rsync可执行程序地址,默认/usr/bin/rsync 可用which rsync查看具体在哪
        archive = true, -- 默认false,以递归方式传输文件,并保持所有文件属性
        compress = false, -- 压缩传输默认为true。在带宽与cpu负载之间权衡,本地目录同步可以考虑把它设为false;
        verbose = true, -- 同步详细模式输出
        perms = true -- perms 保留文件权限,默认为true;
    }
}

如果是不同多台服务器之间的数据同步,比如A服务器数据同步到B服务上,那么你就需要在A服务器上配置Lsyncd服务,并且编写配置文件。那么常用配置如下:

-- 全局配置
settings {
    logfile ="/var/log/lsyncd/lsyncd.log", -- 日志文件存放路径
    statusFile ="/var/log/lsyncd/lsyncd.status", -- 状态文件存放路径
    inotifyMode = "CloseWrite", --
    maxProcesses = 8,-- 同步进程的最大个数。假如同时有20个文件需要同步,而maxProcesses = 8,则最大能看到有8个rysnc进程
    -- nodaemon =true, 表示不启用守护模式,默认;
}
       
-- sync部分配置
sync {
    
    default.rsync,-- 有rsync、rsyncssh、direct三种模式
    source = "本地绝对路径 源目录", -- source 同步的源目录,使用绝对路径
    target = "服务器用户名@服务器IP:目标服务器数据存放绝对路径", -- target 定义目的地址.对应不同的模式有不同写法
    exclude = { "*.tmp", "*.log", ".git/" }, -- 排除的文件
    
    -- rsync部分配置
    rsync = {
        -- bwlimit=200, -- bwlimit 限速,单位kb/s,与rsync相同
        binary = "/usr/bin/rsync", -- rsync可执行程序地址,默认/usr/bin/rsync 可用which rsync查看具体在哪
        archive = true, -- 默认false,以递归方式传输文件,并保持所有文件属性
        compress = false, -- 压缩传输默认为true。在带宽与cpu负载之间权衡,本地目录同步可以考虑把它设为false;
        verbose = true, -- 同步详细模式输出
        perms = true, -- perms 保留文件权限,默认为true;
	    
	    	rsh = "ssh -i /root/.ssh/id_ed25519 -p 22 -o StrictHostKeyChecking=no",  -- 使用密钥认证
    }
}

可见,不同服务器之间同步数据,需要配置SSH,但实际同步时你会发现每次同步都会提示输入ssh的密码,配置免密登录即可!

由于你是A服务器数据同步到B服务器上,那么就相当于你服务器A要免密登陆到服务器B,所以你要在服务器B上配置免密登陆。

在服务器A上生成SSH密钥,并且配置免密登陆到B:

  1. 生成SSH登陆密钥:(默认路径:~/.ssh/id_ed25519.pub

    ssh-keygen -t ed25519
    
  2. 将公钥复制到目标服务器B

    ssh-copy-id user@server_b_ip
    

注意:复制密钥到目标服务器的时候,需要你输入目标服务器的密码,如果你的服务器配置了仅可密钥登陆,那么这里你是登陆不上的,必须是密码而不是密钥。 如图:

登陆必须开启密码登陆

配置好了之后,我们来测试免密SSH登陆:

ssh user@server_b_ip

如果这里无需密码即可登录,那么就说明配置都完成了。