暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Linux 上使用 lsyncd 实时同步目录

watson 2024-08-05
2159

1. 写在前面

Lsyncd (Live Syncing Daemon) 轻量级本地与远程实时同步解决方案,遵循 GPL-2.0 license。本文将通过示例介绍如何在 Linux 环境中执行实时同步操作。

2. 概述

Lsyncd 使用文件系统事件接口(inotify 或 fsevents)来监视本地文件和目录的更改,并在短时内汇总合并事件,然后启动一个或多个进程将更改同步到远程文件系统,默认同步方式是 rsync 模式。

安装相对简单,对系统本身没有太多要求,也不会影响本地文件系统的性能。

作为 rsync 的替代方案,lsyncd 可以通过 rsync+ssh 模式提高同步效率,例如,重命名文件/目录或者移动位置(普通 rsync 通过删除旧文件然后重新传输整个文件来执行移动)。

优点:

  • 实时同步(单向):lsyncd 通过监控文件系统事件(inotify 或 fsevents),可以在文件变化时触发同步;

  • 基于 rsync:使用 rsync 进行实际的文件传输,继承 rsync 高效性和灵活性;

  • 自动化:配置好,lsyncd 可以自动监控和同步文件变化;

  • 灵活性:通过 Lua 脚本配置,定制同步行为

缺点:

  • 复杂性:配置文件高级用法可能对刚接触用户来说有些复杂;

  • 资源消耗:实时监控和同步可能会消耗一定的系统资源,特别是在有大量文件变化的情况下;

  • 延迟问题:尽管是实时同步,但对于非常频繁的变化,可能会有轻微的延迟;

使用场景:

  • 日志文件同步:在需要实时同步日志文件到远程服务器进行分析时,lsyncd 非常有用;

  • 实时备份:适用于需要实时备份重要数据的场景;

  • Web 服务器文件同步:在多台 Web 服务器之间同步静态文件,确保所有服务器上的文件保持一致;

3. 安装

Lsyncd 可在 Fedora、Debian 和 Ubuntu 的官方软件仓库中找到,例如:在 Debian 及其衍生版本上进行安装,可以使用 apt:

sudo apt install lsyncd

要在 Fedora 上安装 lsyncd,可以使用:

sudo dnf install lsyncd

lsyncd 不是 RHEL/CentOS 7 默认仓库的一部分,因此必须使用 EPEL 仓库安装它,可以使用以下命令安装 epel-repo:

[root@centos-7 ~]# yum -y install epel-release

安装 lsyncd:

[root@centos-7 ~]# yum -y install lsyncd

4. 配置 lsyncd

lsyncd 使用 Lua 配置文件,通常位于 /etc/lsyncd/lsyncd.conf.lua,也可以通过以下方式查看路径:

查看:systemctl status lsyncd

root@jpzhang-dev:~# systemctl status lsyncd
● lsyncd.service - LSB: lsyncd daemon init script
Loaded: loaded (/etc/init.d/lsyncd; generated)
Active: active (exited) since Tue 2024-07-30 00:31:05 CST; 23h ago
... ...

查看:/etc/init.d/lsyncd

... ...
CONFIG=/etc/lsyncd/lsyncd.conf.lua
... ...

默认配置路径:/etc/lsyncd/lsyncd.conf.lua,如果不存在则新建,或者从 /usr/share/doc/lsyncd*/examples 提供的示例中拷贝一份进行修改。

官方示例:

root@jpzhang-dev:/home/workspace/linux# ls /usr/share/doc/lsyncd*/examples
lalarm.lua lbash.lua lecho.lua lftp.lua lgforce.lua limagemagic.lua lpostcmd.lua lrsync.lua lrsyncssh.lua ls3.lua.gz lsayirc.lua

例如,下面配置:

settings {
logfile = "/var/log/lsyncd/lsyncd.log", -- 指定日志文件路径
statusFile = "/var/log/lsyncd-status.log", -- 指定状态文件路径
statusInterval = 20, -- 每 20 秒写入一次状态文件
nodaemon = true -- 守护进程模式运行
}

lsyncd 的配置文件是用 Lua 脚本编写的,支持高度的自定义。

以下是配置文件中的主要选项:

(1) settings 表

settings 表用于定义全局设置。

settings {
logfile = "/var/log/lsyncd/lsyncd.log", -- 指定日志文件路径
statusFile = "/var/log/lsyncd-status.log", -- 指定状态文件路径
inotifyMode = "CloseWrite or Modify", -- 指定 inotify 事件模式
statusInterval = 20, -- 每 20 秒写入一次状态文件
nodaemon = true -- 守护进程模式运行
}
  • logfile: 日志文件路径,用于记录 lsyncd 的运行日志;

    logfile    = "/var/log/lsyncd/lsyncd.log",
  • statusFile: 状态文件路径,用于记录 lsyncd 的状态信息;

    statusFile = "/var/log/lsyncd/lsyncd.status",
  • statusInterval: 设置写入状态文件的间隔时间,以秒为单位,默认 10s;

    statusInterval = 20,
  • nodaemon: 设置 lsyncd 以守护进程模式运行 true/false;

    nodaemon   = true,
  • inotifyMode: 指定 inotify 事件模式;

    inotifyMode = "CloseWrite or Modify"
  • maxProcesses:限制并发的进程数;

    maxProcesses = 1
  • delay:设置同步的延迟时间(秒);

    delay = 15

(2) sync 表

sync 表用于定义同步任务。

  • default(必需)

    指定要使用的同步模式,常用的同步模式有 default.rsync 和 default.direct。

    default.rsync
    • default.rsync: 使用 rsync 进行同步;

    • default.direct: 直接复制文件,不使用 rsync;

  • source(必需) 

    定义源目录的路径。

    source = "/path/to/source"
  • target(必需)

    定义目标目录的路径,可以是本地路径或远程路径。

    target = "/path/to/target"
  • delay

    设置同步延迟时间(以秒为单位),表示在检测到文件更改后等待多长时间再进行同步。

    delay = 10
  • exclude

    指定要排除的文件或目录的模式列表。

    exclude = { "*.tmp", "*.log", "cache/", "temp/" }
  • excludeFrom

    指定一个包含要排除文件和目录列表的文件路径。

    excludeFrom = "/path/to/exclude-list.txt"
  • rsync

    指定 rsync 相关的配置参数。

    rsync = {
    binary = "/usr/bin/rsync", -- rsync 可执行文件路径
    archive = true, -- 归档模式(保留权限、时间戳等)
    compress = false, -- 不压缩数据
    delete = true, -- 删除目标目录中不在源目录中的文件
    verbose = true -- 显示详细输出
    }
  • init

    初始化同步时执行的脚本。

    init = function(event)
    os.execute("sh /path/to/scripts/init_script.sh")
    return false -- 阻止默认的 init 同步
    end
  • collect

    在收集完所有变化但尚未开始同步操作时执行的脚本。

    collect = function(event)
    os.execute("sh /path/to/scripts/collect_sync.sh")
    end
  • action

    定义在执行同步操作时的自定义行为。

    action = function(inlet)
    local result = Rsync(inlet, true) -- 执行 rsync 操作
    os.execute("sh /path/to/scripts/post_sync.sh")
    return result
    end

完整示例

settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10
}

sync {
default.rsync,
source = "/path/to/source",
target = "/path/to/target",
delay = 10,
exclude = { "*.tmp", "*.log", "cache/", "temp/" },
excludeFrom = "/path/to/exclude-list.txt",
rsync = {
binary = "/usr/bin/rsync", -- rsync 可执行文件路径
archive = true, -- 归档模式(保留权限、时间戳等)
compress = false, -- 不压缩数据
delete = true, -- 删除目标目录中不在源目录中的文件
verbose = true -- 显示详细输出
},
init = function(event)
os.execute("sh /path/to/scripts/init_script.sh")
return false -- 阻止默认的 init 同步
end,
collect = function(event)
os.execute("sh /path/to/scripts/collect_sync.sh")
end,
action = function(inlet)
local result = Rsync(inlet, true) -- 执行 rsync 操作
os.execute("sh /path/to/scripts/post_sync.sh")
return result
end
}

更多设置,请查看 lysyncd 官方页面;

5. 启动和管理 lsyncd 服务

  • 启动 lsyncd: 

    sudo systemctl start lsyncd
  • 开机自启:

    sudo systemctl enable lsyncd
  • 检查状态:

    sudo systemctl status lsyncd
  • 查看日志:

    配置文件配置,默认 Linux 在 syslog 打印日志;

    tail -f /var/log/lsyncd/lsyncd.log

6. 10+ lsyncd 示例

6.1 命令行:实时同步目录&文件

6.1.1 运行时参数说明

  • -help: 显示帮助信息

    lsyncd -help
  • -version: 显示 lsyncd 版本信息

    lsyncd -version
  • -nodaemon: 以非守护进程模式运行 lsyncd,便于调试

    lsyncd -nodaemon /path/to/config.lua
  • -log Exec, -log Minimal: 设置日志级别

    lsyncd -log Exec /path/to/config.lua
    lsyncd -log Minimal /path/to/config.lua
  • -rsync [source] [target]: 直接从命令行启动 lsyncd,使用 rsync 模式同步源和目标目录

    lsyncd -rsync /source/ /target/

6.1.2 用例说明

示例环境:

root@jpzhang-dev:/home/workspace/linux# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 20.04.6 LTS
Release: 20.04
Codename: focal

使用 lsyncd rsync 同步 localhost 上的目录:

-rsync [source] [target]: 直接从命令行启动 lsyncd,并使用 rsync 模式同步源和目标目录。

root@jpzhang-dev:/home/workspace/linux# ls
source target

root@jpzhang-dev:/home/workspace/linux# lsyncd -rsync /home/workspace/linux/source/ /home/workspace/linux/target/
11:20:35 Normal: --- Startup, daemonizing ---

root@jpzhang-dev:/home/workspace/linux# ps -aux | grep lsyncd
root 903394 0.0 0.0 4508 2152 ? Ss 16:57 0:00 lsyncd -rsync /home/workspace/linux/source/ /home/workspace/linux/target

root@jpzhang-dev:/home/workspace/linux# echo 'Hello world!!!' > ./source/jpzhang.txt
root@jpzhang-dev:/home/workspace/linux# echo '========' >> ./source/jpzhang.txt

【注意】 

  • source & target 需要配置绝对路径;

  • 默认通过 syslog 输出日志;

lsyncd 进程进入后台,作为守护进程运行,也可以 添加 -nodaemon 参数,以非守护进程模式运行 lsyncd,便于调试。

root@jpzhang-dev:/home/workspace/linux# lsyncd -nodaemon -rsync /home/workspace/linux/source/ /home/workspace/linux/target
17:46:25 Normal: --- Startup ---
17:46:25 Normal: recursive startup rsync: /home/workspace/linux/source/ -> /home/workspace/linux/target/
17:46:25 Normal: Startup of /home/workspace/linux/source/ -> /home/workspace/linux/target/ finished.
17:48:16 Normal: Calling rsync with filter-list of new/modified files/dirs
/jpzhang.txt
/
17:48:16 Normal: Finished a list after exitcode: 0

source 内容变更:

root@jpzhang-dev:/home/workspace/linux# echo 'edit content~~' >> ./source/jpzhang.txt
root@jpzhang-dev:/home/workspace/linux# cat target/jpzhang.txt
Hello world!!!
========
edit content~~

要跨主机同步文件和目录

(1)使用: rsync 模式

root@jpzhang-dev:/home/workspace/linux# lsyncd -nodaemon -rsync  /home/workspace/linux/source/ linux-dev:/home/tmp/target
17:52:10 Normal: --- Startup ---
17:52:10 Normal: recursive startup rsync: /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/
17:52:11 Normal: Startup of /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/ finished.
17:53:09 Normal: Calling rsync with filter-list of new/modified files/dirs
/jpzhang.txt
/
17:53:10 Normal: Finished a list after exitcode: 0

source 内容变更:

root@jpzhang-dev:/home/workspace/linux# echo 'To sync files and directories across hosts' >> ./source/jpzhang.txt

Linux-dev:
root@zhangjianpeng:/home/tmp/target# cat jpzhang.txt
Hello world!!!
========
edit content~~
To sync files and directories across hosts

【注意】

  • /etc/host: 添加域名映射;

  • host1(源) ->host2(目标):无密访问;

(2)使用:rsyncssh 模式

root@jpzhang-dev:/home/workspace/linux# lsyncd -nodaemon -rsyncssh /home/workspace/linux/source/ linux-dev /home/tmp/target
17:58:53 Normal: --- Startup ---
17:58:53 Normal: recursive startup rsync: /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/
17:58:54 Normal: Startup of "/home/workspace/linux/source/" finished: 0

6.2 使用 default.direct 同步本地目录和文件

lsyncd 的 default.direct 模式使用的是 cp、rm 和 mv 命令进行文件的复制、删除和移动操作,这与 rsync 模式的不同之处在于其不依赖于 rsync 工具。这种模式适用于在本地文件系统之间进行简单同步,或者在不需要使用 rsync 提供的高级选项和功能的情况下使用,不适用于跨网络同步,因为 cp、rm 和 mv 都是本地文件操作命令。

以下是一个使用 default.direct 模式的 lsyncd 配置文件示例:

/etc/lsyncd/lsyncd.conf.lua:

settings {
logfile = "/var/log/lsyncd/lsyncd.log", -- 指定日志文件路径
statusFile = "/var/log/lsyncd/lsyncd.status", -- 指定状态文件路径
statusInterval = 10, -- 每 10 秒写入一次状态文件
inotifyMode = "CloseWrite or Modify" -- 设置 inotify 事件模式
}

sync {
default.direct, -- 使用 default.direct 模式进行同步
source = "/home/workspace/linux/source/", -- 本地源目录路径
target = "/home/workspace/linux/target", -- 本地目标目录路径
delay = 5, -- 设置文件系统事件到实际同步操作之间的延迟时间
excludeFrom = "/home/workspace/linux/exclude-list.txt", -- 排除的文件或目录列表
maxProcesses = 1 -- 限制同时运行的同步进程数
}

重启 lsyncd:

systemctl restart lsyncd

查看日志:

root@jpzhang-dev:~# tail -f /var/log/lsyncd/lsyncd.log

Tue Jul 30 23:56:55 2024 Normal: --- Startup, daemonizing ---
Tue Jul 30 23:56:55 2024 Normal: recursive startup rsync: /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/
Tue Jul 30 23:56:56 2024 Normal: Startup of /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/ finished.

6.3 使用 default.rsync 将本地主机上的源文件和目录同步到另一台目标主机上

default.rsync 模式使用 rsync 工具进行同步,可以在本地或通过网络同步目录。rsync 提供了高级选项,如差异同步、压缩和删除目标中不在源中的文件。

修改默认配置:/etc/lsyncd/lsyncd.conf.lua

root@jpzhang-dev:/home/workspace/linux/source# cat /etc/lsyncd/lsyncd.conf.lua 
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "linux-dev:/home/tmp/target",
delay = 5,
maxProcesses = 1
}

重启 rsync:systemctl restart lsyncd

6.4 使用 default.rsyncssh 将本地主机上的源目录和文件同步到不同的目标主机上

lsyncd 还可以配置使用 ssh 命令在目标主机移动文件或目录,这样可以避免重复传输相同的文件。

原理:当文件发生变化时,lsyncd 会生成一个 rsync 进程,通过 ssh 命令连接到目标主机。在目标主机上,文件或目录会被本地移动(使用 mv 命令),而不是被删除并重新传输。这种方法可以有效减少网络传输量,提高同步效率。

root@jpzhang-dev:/home/workspace/linux/source# cat /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

sync {
default.rsyncssh,
source = "/home/workspace/linux/source/",
target = "linux-dev:/home/tmp/target",
delay = 5,
maxProcesses = 1
}

6.5 使用 lsyncd 为目录启用压缩和递归功能

同步文件时启用压缩和递归功能。 

  • archive = true:递归同步并保留文件属性;

  • compress = false:不压缩数据,减少 CPU 负担(可以根据需要设置为 true);

root@jpzhang-dev:/home//workspace/linux/source# cat /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "linux-dev:/home/tmp/target",
delay = 5,
maxProcesses = 1,
rsync = {
archive = true,
compress = true
}
}

6.6 同步到多个目标目录

在 Linux 中使用 lsyncd 从一个源目录同步到多个目标目录,可以通过两种主要方法实现:创建单独的同步任务,或者使用 for 循环动态生成同步任务。

以下是两种方法的详细说明和示例配置。

方法一:创建单独的同步任务

通过在配置文件中为每个目标目录创建单独的同步任务,可以明确地定义每个同步任务的参数和行为。这种方法适用于需要对每个同步任务进行特定配置的情况。

root@jpzhang-dev:/home/workspace/linux# cat /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "/home/workspace/linux/target",
delay = 5,
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "/home/workspace/linux/target2",
delay = 5,
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "linux-dev:/home/tmp/target",
delay = 5,
}

方法二:使用 for 循环动态生成同步任务

通过使用 Lua 语言中的 for 循环,可以动态生成多个同步任务。这种方法适用于目标目录较多且配置相似的情况,简化配置文件的编写和维护。

root@jpzhang-dev:/home/workspace/linux# cat /etc/lsyncd/lsyncd.conf.lua

settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

targets = {
"/home/workspace/linux/target",
"/home/workspace/linux/target2",
"linux-dev:/home/tmp/target",
}

for _, target in ipairs( targets )
do
sync{ default.rsync, source='/home/workspace/linux/source/', target=target }
end

重启: systemctl restart lsyncd日志输出: less /var/log/lsyncd/lsyncd.log

... ...
Tue Jul 30 23:59:07 2024 Normal: Finished a list after exitcode: 0
Wed Jul 31 10:46:04 2024 Normal: --- TERM signal, fading ---
Wed Jul 31 10:46:04 2024 Normal: --- Startup, daemonizing ---
Wed Jul 31 10:46:04 2024 Normal: recursive startup rsync: /home/workspace/linux/source/ -> /home/workspace/linux/target/
Wed Jul 31 10:46:04 2024 Normal: recursive startup rsync: /home/workspace/linux/source/ -> /home/workspace/linux/target2/
Wed Jul 31 10:46:04 2024 Normal: recursive startup rsync: /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/
Wed Jul 31 10:46:04 2024 Normal: Startup of /home/workspace/linux/source/ -> /home/workspace/linux/target2/ finished.
Wed Jul 31 10:46:04 2024 Normal: Startup of /home/workspace/linux/source/ -> /home/workspace/linux/target/ finished.
Wed Jul 31 10:46:05 2024 Normal: Startup of /home/workspace/linux/source/ -> linux-dev:/home/tmp/target/ finished.

6.7 在 rsync 操作前后执行脚本

在 lsyncd 中,你可以配置在 rsync 操作前后执行脚本,

示例:源和目标同步完成,执行 “target1_status.sh” 脚本,打印 “Completed sync in target”,可用于检查目录同步退出状态。

root@jpzhang-dev:/home/workspace/linux# cat /etc/lsyncd/lsyncd.conf.lua
settings {
logfile = "/var/log/lsyncd/lsyncd.log",
statusFile = "/var/log/lsyncd/lsyncd.status",
statusInterval = 10,
inotifyMode = "CloseWrite or Modify",
}

sync {
default.rsync,
source = "/home/workspace/linux/source/",
target = "/home/workspace/linux/target",
delay = 5,
rsync = {
binary = "/home/workspace/linux/lsyncd/target1_status.sh",
},
}

target1_status.sh:

root@jpzhang-dev:/home/workspace/linux# cat lsyncd/target1_status.sh
#!/bin/bash
/usr/bin/rsync "$@"
result=$?
(
if [ $result -eq 0 ]; then
echo "`date`: Completed sync in target" >> /var/log/lsyncd/custom_scripts.log
fi
) >/dev/null 2>/dev/null </dev/null

exit $result

6.8 排除文件和目录

在 lsyncd 中,可以通过配置 exclude 和 excludeFrom 参数来排除特定的文件和目录。

  • exclude:用于排除指定的文件和目录,可以使用通配符来匹配文件和目录名称:

    exclude = { "*.tmp", "*.log", "cache/", "temp/" }

    以上配置将排除所有以 .tmp 和 .log 结尾的文件,以及名为 cache/ 和 temp/ 的目录。

  • excludeFrom: 参数指定一个包含要排除文件和目录列表的文件路径,这个文件中的每一行都代表一个排除模式:

    创建 exclude-list.txt 文,添加要排除的文件和目录模式:

    # /path/to/exclude-list.txt
    *.tmp
    *.log
    cache/
    temp/

    然后在配置文件中引用这个文件:excludeFrom = "/path/to/exclude-list.txt"

6.9 同步目录删除文件

默认情况下,Lsyncd 会删除目标目录中那些在源目录中已经不存在的文件,以保持目标目录与源目录的同步。这是确保同步完整性的基本操作。然而,用户可能会出于各种原因需要排除某些情况,因此 delete 选项在默认配置中通常是作为附加参数使用。

delete 选项的有效值包括:

  • delete = true:默认值,Lsyncd 会在目标目录中删除源目录中没有的内容,无论是在启动时还是正常运行时;

  • delete = false:不会删除目标目录中的任何文件,无论是启动时还是正常运行时(但可以重写);

  • delete = 'startup':Lsyncd 在启动时会删除目标目录中的文件,但在正常运行时不会删除;

  • delete = 'running':Lsyncd 在启动时不会删除目标目录中的文件,但在正常运行时会删除;

sync {
default.direct,
source = "/source",
target = "/target1",
delay = 10,
delete = false
}
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论