Linux tmpfiles.d 怎样为运行时目录设置保留策略
Linux 服务经常需要一个短生命周期目录:套接字放在 /run,临时状态放在某个运行时路径,旧缓存则希望按年龄清掉。把这些动作散落在启动脚本里,容易出现目录不存在、权限被改坏、重启后残留或清理范围过大的问题。tmpfiles.d 的作用,就是把“路径应该是什么状态”写成规则,再交给 systemd-tmpfiles 统一创建、修复和清理。
官方地址:https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html
最小思路是:用d声明目录,用字段写明 mode、属主和清理年龄;先用systemd-tmpfiles --create --boot或--clean预览规则,再把确认过的动作交给系统服务。tmpfiles.d 不是备份工具,也不应该用宽泛路径替代明确的应用目录。
先把“创建”和“清理”拆成两件事
我在处理运行时目录时,先问两个问题:这个路径在启动后必须存在吗?里面的旧内容是否有明确的生命周期?前一个问题对应创建或权限状态,后一个问题才对应清理年龄。两者可以写在同一条规则里,但判断依据不同。
| 目标 | 适合的动作 | 不能直接推出的结论 |
|---|---|---|
| 目录缺失 | 使用目录类型规则创建 | 目录里的业务文件可以随意删除 |
| 目录权限变化 | 声明 mode、user、group,必要时恢复状态 | 应用一定能在当前用户下写入 |
| 旧临时内容 | 给规则设置 age,让 clean 选择过期项 | 这等同于备份或灾备 |

用 d 规则声明 /run 下的目录
目录规则的核心是类型、路径、权限、属主、属组和年龄字段。下面以一个应用缓存目录为例,路径故意保持具体,避免使用 /run/* 之类难以审查的通配范围:
# /etc/tmpfiles.d/app-cache.conf # d 表示:目标是目录;0750、app、app 是目录的期望状态 d /run/app-cache 0750 app app 7d
这行的含义不是“每次都删除并重建目录”,而是声明一个目录状态:目录不存在时可以创建,状态需要维护时由 tmpfiles 处理,7d 则为该路径下可参与清理的内容提供年龄条件。运行用户、组名和权限要与应用实际访问模型一致,不能因为目录位于 /run 就默认所有服务都能写入。
规则文件通常放在 /etc/tmpfiles.d/,用于管理员或本机配置;发行版提供的规则常见于 /usr/lib/tmpfiles.d/,本机运行时生成或临时覆盖的规则可能位于 /run/tmpfiles.d/。同名文件存在时,优先级和覆盖关系要按官方规则确认,避免直接修改包管理器维护的文件。
v、d 和 Z:不要把类型字母当成装饰
不同类型代表不同的维护语义。日常配置中最容易混淆的是目录、易失文件和权限恢复:d 面向目录,v 面向易失文件或目录并带有清理语义,Z 主要用于恢复文件上下文而不是替代目录创建。

| 类型方向 | 适用问题 | 写规则前要确认 |
|---|---|---|
d | 目录应存在,并有明确权限和属主 | 应用启动是否依赖它,以及父目录是否可访问 |
v | 易失内容需要创建并按年龄管理 | 删除旧内容是否真的安全,年龄如何定义 |
Z | 需要恢复安全上下文的文件树 | 系统是否使用对应的安全模块,恢复范围是否足够窄 |
如果目标只是创建一个目录,优先用最小的 d 规则;如果目标是让应用的缓存文件按年龄清理,才考虑带清理字段的类型或规则组合。把 Z 当成“创建目录”的替代写法,会让排查方向偏离真正的问题。
先预览,再分别执行 create 和 clean
systemd-tmpfiles 提供了按动作处理规则的入口。我的习惯是先以 dry-run 方式观察目标,再决定是否在测试主机上执行:
# 只查看规则会匹配哪些创建动作,不立即修改文件系统 sudo systemd-tmpfiles --create --boot --prefix=/run/app-cache --dry-run # 确认输出只涉及应用目录后,再执行创建和状态维护 sudo systemd-tmpfiles --create --boot --prefix=/run/app-cache # 单独执行清理;--prefix 把范围限制在明确的应用路径 sudo systemd-tmpfiles --clean --prefix=/run/app-cache
不同 systemd 版本对可选参数和输出细节可能有所差异,部署前应以本机的 systemd-tmpfiles --help 和对应 man page 为准。这里最重要的边界是把 --create 与 --clean 分开理解:前者让声明的目录状态落地,后者按规则年龄处理已有内容。
如果不使用 --prefix,就要更加谨慎地审阅规则来源。系统级 clean 可能包含许多发行版自带路径;对单个应用调试时,把范围缩窄到明确目录更容易判断风险。
怎样判断清理年龄是否真的适合
年龄字段不是“文件创建时间超过七天就一定删除”的简单承诺。tmpfiles 的清理判断与规则类型、目录递归方式、文件时间戳和本机实现有关,因此应该把它理解为“符合该规则的旧内容进入清理候选”。持久化数据、上传文件和用户生成内容,不应只依赖 tmpfiles 的 age 作为保护措施。
# 先列出目标目录的内容与时间,再决定 age 是否合适 target=/run/app-cache # -a 保留隐藏项,--time-style 让人工记录更容易比较 find "$target" -mindepth 1 -maxdepth 2 -printf '%TY-%Tm-%Td %TH:%TM %p\n' | sort # 规则只用于短生命周期内容;持久数据应交给应用或备份系统管理 sudo systemd-tmpfiles --clean --prefix="$target"
如果应用会重新打开旧文件并更新访问时间,清理结果还会受这些时间变化影响。反过来,应用若把重要数据放在运行时目录,clean 可能在你没有设计恢复路径时删除它。更稳妥的分层是:/run 放可重建状态,缓存可被重新生成,真正需要留存的数据放到持久化目录并由专门的备份和保留策略管理。
规则不生效时,按来源和范围排查
遇到“目录没有创建”或“旧文件没有清掉”,先确认系统真正读取了哪一个规则文件。不要一开始就重复执行同一个命令;先分清文件路径、类型、权限、属主和 age 是否写在了预期字段。
# 展示系统已安装的 tmpfiles 规则,先确认同名覆盖和目录来源 systemd-tmpfiles --cat-config # 只用指定规则文件做一次局部预览,避免把全局规则混进判断 sudo systemd-tmpfiles --create --dry-run /etc/tmpfiles.d/app-cache.conf # 查看目标的实际权限、属主和内容,核对规则写入的期望状态 stat -c '%A %U:%G %n' /run/app-cache find /run/app-cache -mindepth 1 -maxdepth 1 -print
排查顺序可以固定为:规则文件是否被读取、路径是否被更具体的规则覆盖、目录的 mode 和属主是否匹配、clean 的年龄是否有可比较的内容、最后才看服务启动时机。若目录由服务自己的 RuntimeDirectory= 创建,应该先明确它与 tmpfiles 规则的职责边界,不要让两个机制同时管理同一组权限。
我的落地清单
- 只为一个应用写一个明确路径,优先从
d规则开始。 - 把 mode、user、group 写清楚,并用测试用户验证最小访问权限。
- 把短生命周期内容和持久数据分开放置,不把 clean 当备份。
- 先用
--dry-run和--prefix观察,再分别执行--create、--clean。 - 系统规则优先查看来源和覆盖关系,不直接改动包管理器维护的文件。
常见问题
tmpfiles.d 会在每次启动时删除整个目录吗?
不会因为目录规则本身就删除整个目录。创建和清理是不同动作,清理还要结合规则类型、年龄和匹配范围。没有明确设计清理语义时,不要把 --clean 当成“重置目录”。
为什么目录已经存在,权限还是没有按规则变化?
可能是规则类型不承担你期待的权限恢复,或者有同名、更高优先级规则覆盖了当前文件。先用 --cat-config 查看最终配置,再对照实际 mode、属主和服务自己的目录管理机制。
可以用 tmpfiles.d 清理应用的数据库目录吗?
除非应用明确把其中内容定义为可丢弃缓存,否则不建议。数据库、上传文件和业务记录需要自己的保留、备份与恢复策略;tmpfiles 更适合运行时目录和可重建的临时内容。
Python tomllib 只读场景下的 TOML 配置写回方案
- 上一篇
- Python tomllib 只读场景下的 TOML 配置写回方案
- 下一篇
- systemd-run 怎样给临时任务设置内存上限
-
- 文章 · linux | 15分钟前 | Linux · Linux 内存限制 MemoryMax systemd-run 临时任务
- systemd-run 怎样给临时任务设置内存上限
- 436浏览 收藏
-
- 文章 · linux | 1天前 |
- install -T 和普通目录安装有什么区别
- 449浏览 收藏
-
- 文章 · linux | 1天前 |
- getent ahostsv4 和 ahostsv6 怎么分别确认地址解析结果
- 131浏览 收藏
-
- 文章 · linux | 1天前 | Linux · ELF readelf DWARF .debug_line 源码行号
- readelf 怎么从 DWARF 行号表找到源码位置映射
- 418浏览 收藏
-
- 文章 · linux | 1天前 |
- openssl speed 怎么公平比较不同算法的吞吐量
- 230浏览 收藏
-
- 文章 · linux | 1天前 |
- wg showconf 怎么导出正在运行的 WireGuard 配置
- 331浏览 收藏
-
- 文章 · linux | 1天前 |
- mount.cifs multiuser 和 cache 选项怎么配合使用
- 266浏览 收藏
-
- 文章 · linux | 1天前 |
- nfsstat -m 怎么查看 NFS 挂载实际使用的选项
- 292浏览 收藏
-
- 文章 · linux | 1天前 |
- tcpdump -D 怎么列出可用抓包接口并避免选错网卡
- 218浏览 收藏
-
- 文章 · linux | 1天前 |
- bpftrace profile 探针怎么按固定频率采样用户态堆栈
- 227浏览 收藏
-
- 文章 · linux | 1天前 |
- ip netns identify 怎么确认进程属于哪个网络命名空间
- 477浏览 收藏
-
- 文章 · linux | 1天前 | 部署 · Linux · systemd attach systemd unit portablectl portable service RootImage
- portablectl attach 怎么把服务镜像接入本机启动流程
- 452浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 917次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 923次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 1016次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 999次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 821次使用
-
- 新能源汽车充电设施巡检记录的设置方法
- 2026-10-04 422浏览
-
- 通信机房巡检怎样记录电源与链路状态
- 2026-11-01 204浏览
-
- 详解golang执行Linuxshell命令完整场景下的使用方法
- 2023-01-07 426浏览
-
- go程序部署到linux上运行的实现方法
- 2023-01-02 387浏览
-
- Linux系统下Go语言开发环境搭建
- 2023-01-07 242浏览

