登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux systemd.path 监听文件变化的触发配置

来源:17golang原创

时间:2026-10-28 13:11:35 123浏览 收藏

Linux 中要在文件变化后触发一个短任务,可以配置一对 systemd 单元:在 .path 的 [Path] 中写绝对路径与触发条件,在对应 .service 中写执行动作。两者同名时默认自动匹配,也可以用 Unit= 明确指定。监听常驻的是路径单元,实际动作可以用 Type=oneshot 执行后退出。

文件变化通知适合提醒服务重新读取当前状态,不应被当成逐条可靠的业务消息队列。先用简单日志动作把配置关系讲清,再换成自己的幂等处理程序。

systemd 官方手册地址:https://www.freedesktop.org/software/systemd/man/latest/systemd.path.html

下面给出一个独立演示:监听 /var/lib/path-demo/settings.conf,变化时输出一条日志。命令是供读者在使用 systemd 的 Linux 测试机上执行的配方,本文没有把它描述成当前环境的实际运行结果。

把监听任务拆成路径条件和执行动作

路径单元 path-demo.path 负责描述“看哪里、什么条件触发”;服务单元 path-demo.service 负责描述“触发后执行什么”。这种拆分让路径监听与业务脚本各自保持简单,脚本不需要自己维护一个无限循环。

正文中的受监控文件、path-demo.path、PathChanged、Unit、path-demo.service 与 ExecStart 构成最小结构。修改业务命令不意味着必须改变监听条件;反过来,从文件变化切换成目录条件,也不应该把整个业务处理写进路径单元。

路径单元与服务单元的静态绑定结构
静态结构图:路径单元包含监听条件和目标单元绑定,执行动作由服务单元的 ExecStart 表达。

最小配方:监听一个配置文件

首先准备独立演示目录和初始文件,再分别保存两个配置文件。以下采用系统级单元,因此写入 /etc/systemd/system 和管理单元需要管理员权限。示例只输出日志;生产动作替换后,应根据所需文件权限配置合适的 User、Group 和访问范围。

# 创建专用演示目录,避免触碰现有业务配置。
sudo install -d -m 0755 /var/lib/path-demo
printf 'mode=initial\n' | sudo tee /var/lib/path-demo/settings.conf >/dev/null

将下面内容保存为 /etc/systemd/system/path-demo.path:

[Unit]
Description=Watch the demo settings file

[Path]
# 监听绝对路径,适用于文件写入关闭等变化。
PathChanged=/var/lib/path-demo/settings.conf
Unit=path-demo.service

[Install]
# 启用路径监听;服务由它按需激活。
WantedBy=multi-user.target

将下面内容保存为 /etc/systemd/system/path-demo.service。先确认测试机的 echo 程序位于 /usr/bin/echo;若发行版路径不同,应改成实际存在的绝对路径。

[Unit]
Description=Record a demo settings change

[Service]
# 短任务执行后退出,便于后续再次触发。
Type=oneshot
ExecStart=/usr/bin/echo path-demo-settings-changed
StandardOutput=journal
StandardError=journal

这里不设置 RemainAfterExit=yes。oneshot 默认不会在命令退出后继续保持为活动服务,后面的变化才有机会再次启动动作。它也不需要单独配置 [Install] 或 enable 服务;需要开机持续监听的是 .path。

# 重新加载单元定义,并启动和启用监听。
sudo systemctl daemon-reload
sudo systemctl enable --now path-demo.path

# 对演示文件写入并关闭,供观察触发行为。
printf 'mode=updated\n' | sudo tee /var/lib/path-demo/settings.conf >/dev/null

# 观察监听状态与动作日志,不将示例写成固定预期输出。
systemctl status path-demo.path --no-pager
sudo journalctl -u path-demo.service -n 20 --no-pager

路径单元正常等待时通常可见 active (waiting),短服务完成后显示 inactive (dead) 不一定是失败。应结合退出状态及 journal 中的动作记录判断,不能要求 oneshot 一直 running。日志动作成功只证明该演示命令执行了,不能证明尚未接入的业务程序完成了重载。

选择 PathChanged 而不是盲目加密触发

PathChanged 不是每次底层 write 都触发,文件为写入而打开并关闭是其关注的变化之一。PathModified 还包含普通写入;PathExists 与 DirectoryNotEmpty 则分别关心路径存在和目录非空。选择依据应是业务条件,不能把更频繁的通知等同于更完整的数据处理。

业务问题可考虑的条件动作应负责的事情
配置文件变化后重新读取PathChanged读取当前完整配置并处理重复调用
还需关注写入过程PathModified自行判断数据是否完整
标记文件出现PathExists完成工作后消除持续条件或记录已处理状态
目录中有待处理文件DirectoryNotEmpty消费目录内容并处理失败项

后两种持续条件尤其要小心:服务结束后会重新检查路径条件,条件仍成立可能立即再次触发。不要让失败文件一直留在入口目录,又用一个立即退出的服务反复处理它。可以设计明确的处理中目录、失败目录和重试策略,而不是简单把启动限速调大。

路径通知、服务状态与业务处理责任关系
静态说明图:文件变化只提供激活信号,当前状态读取、幂等处理和失败处置仍属于业务程序。

处理原子替换、启动状态和重复变化

有些编辑器采用临时文件写入后替换原文件。对这类生产者,应围绕其实际保存方式设计演示,再决定监听目标文件还是父目录。监听目录会扩大关注范围,处理程序必须自己选定目标,不能假定每次激活都对应同一个具体文件。

PathChanged 不因为监听启动时文件已经存在就自动执行一次。若业务需要初始同步,可以明确安排一次服务启动,再交给路径监听接收后续变化。不要为弥补初始执行而同时增加 PathExists,却忘记存在条件可能长期成立。

路径单元也不会把同一个活动服务变成任意多个并发实例。业务程序应在被唤醒时读取当前状态,并接受通知合并、快速连续变化和重复调用;若必须保存每一项变更,应由生产者写入持久任务记录。该机制使用 inotify,远程 NFS 上由其他机器产生的变化不能据此保证被监测。

用状态与日志定位失败并停用

没有日志时,先区分路径单元没启动、服务定义没加载、命令路径不存在、业务命令退出失败这几种情况。修改单元文件后需要 daemon-reload;修改 .path 的监听配置后,还应重启该路径单元使新配置用于当前监听。

# 查看实际单元内容与最近失败,不仅看是否已经 enable。
systemctl cat path-demo.path path-demo.service
systemctl status path-demo.path path-demo.service --no-pager
sudo journalctl -u path-demo.path -u path-demo.service -n 40 --no-pager

# 仅在修复触发循环或命令错误后清除失败状态并重启监听。
sudo systemctl reset-failed path-demo.path path-demo.service
sudo systemctl restart path-demo.path

# 不再需要演示时停用监听,并停止可能仍在执行的动作。
sudo systemctl disable --now path-demo.path
sudo systemctl stop path-demo.service

重复激活可能触及服务启动限速,路径单元也可能随之失败。较新版本还有路径自身的触发限速选项;本文最小配方不依赖这些新增参数,使用时以目标机器的 man systemd.path 为准。修复原因之后再恢复,不能靠循环 reset-failed 掩盖故障。

enable 服务就能开始监听吗?

不能。需要启动 .path;.service 保存的是动作配置。本文通过 enable --now 同时安排开机启用并立即开始监听。

文件变化后能立即安全重载业务吗?

还需要生产者与消费者约定。写入结束不自动代表业务配置合法,重载程序应自行处理完整性和错误,并保持重复调用可接受。

可以拿它替代消息队列吗?

如果需求只是重新读取最新状态,路径激活很合适;如果每一项变化都必须留痕并逐条确认,应保留持久任务记录,不能依赖文件通知次数作为业务次数。

官方资料:systemd.path 监听条件、服务类型与执行动作、systemctl 单元管理。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>