概述
/usr/lib/tmpfiles.d/(以及 /etc/tmpfiles.d/、/run/tmpfiles.d/)是 systemd tmpfiles 机制 的核心配置目录,用于声明式管理临时文件和目录的创建、清理与权限设置。
这是现代 Linux 系统(使用 systemd)中替代传统 rc.local 或启动脚本 来管理 /tmp、/var/tmp、运行时目录等的标准方式。
核心作用
通过在 tmpfiles.d/ 目录下放置配置文件,可以告诉 systemd:
- 在系统启动时 创建哪些目录/文件
- 定期清理 哪些临时文件(按时间)
- 设置正确的权限、所有者
- 排除某些路径不被清理
这些操作由两个 systemd 单元自动执行:
systemd-tmpfiles-setup.service:在 启动早期 执行(创建目录、设权限)
systemd-tmpfiles-clean.timer:每天定时执行(清理过期文件)
配置语法
每个配置文件(如 tmp.conf)包含多行,每行格式为:
xml
<type> <path> <mode> <user> <group> <age> [<argument>]
关键字段说明
| 字段 | 说明 |
|---|---|
| type | 操作类型(见下表) |
| path | 文件或目录路径(支持通配符 *、?,占位符 %m, %b 等) |
| mode | 权限(八进制,如 0755),可写 - 表示不修改 |
| user | 所有者(用户名或 UID),- 表示不修改 |
| group | 所属组(组名或 GID),- 表示不修改 |
| age | 老化时间(如 10d = 10天),仅对 d, D, q, v 等类型有效 |
| argument | 可选参数(如符号链接目标、ACL 规则等) |
常用类型详解
| 类型 | 作用 |
| d | 创建目录(若不存在),递归设权限 |
| D | 创建目录,并清空其内容(危险!) |
| f | 写入文件内容(需配合 ) |
| F | 创建文件(空),设权限 |
| L | 创建符号链接( 为目标) |
| c / b | 创建字符/块设备(需 root) |
| p / P | 创建 FIFO(命名管道) |
| q | 安静清理目录(保留目录,删过期内容) ✅ |
| Q | 同 q,但不递归子目录 ✅ |
| r / R | 删除文件/目录(R=递归) |
| x | 排除路径(不清理,但会进入子目录) --- |
| X | 完全排除路径(不清理,也不进子目录) |
| z / Z | 递归设置权限/SELinux 上下文(Z=重置 ACL) |
重点
q 是 /tmp 清理的标准方式(安全、高效)
x / X 用于保护特殊目录(如 systemd 私有临时目录)
典型配置示例
- 清理 /tmp(来自 tmp.conf)
xml
q /tmp 1777 root root 10d
- 每天清理 /tmp 中 10 天内未访问/修改 的文件
- 保留 /tmp 目录本身,权限设为 1777(sticky bit:所有用户可读写,但只能删除自己的文件)
- 创建应用运行时目录
xml
# /etc/tmpfiles.d/myapp.conf
d /run/myapp 0755 myuser mygroup -
- 启动时创建 /run/myapp,属主 myuser:mygroup
- 用于存放 PID 文件、socket 等
- 保护私有临时目录(systemd PrivateTmp)
xml
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
- %b = boot ID(每次启动唯一,查看方式 cat /proc/sys/kernel/random/boot_id)
- 防止全局清理规则误删服务私有临时空间
- 创建日志目录并设权限
xml
d /var/log/myapp 0750 appuser adm 7d
- 创建日志目录,7 天后清理过期日志(需日志轮转配合)
配置文件优先级
systemd 按以下顺序读取配置(后加载的覆盖先加载的):
- /usr/lib/tmpfiles.d/*.conf → 系统默认
- /run/tmpfiles.d/*.conf → 运行时临时覆盖
- /etc/tmpfiles.d/*.conf → 管理员自定义(最高优先级)
最佳实践:自定义规则放在 /etc/tmpfiles.d/,不要修改 /usr/lib/ 下的文件。
手动触发操作
应用配置(创建目录/设权限)
xml
sudo systemd-tmpfiles --create
手动清理过期文件
xml
sudo systemd-tmpfiles --clean
查看将执行的操作(dry-run)
xml
systemd-tmpfiles --create --cat-config #较老版本
systemd-tmpfiles --create --dry-run #内核比较新的版本,自行测试
⚠️ 注意事项
1.age 时间基于 atime/mtime
- 文件若 10 天内未被访问或修改,才会被删
- 某些应用(如数据库)会频繁 touch 文件,导致无法清理
2.不要用 D 清空关键目录
- D /tmp 会删除所有内容,包括正在使用的 socket,可能导致服务异常
3./tmp vs /var/tmp
- /tmp:重启可清(通常 tmpfs)
- /var/tmp:跨重启保留,清理周期更长(如 30 天)
4.容器环境可能不生效 - Docker/Podman 容器默认不运行 systemd-tmpfiles,需手动处理
实例说明
xml
在测试机或容器中运行
如果有 Docker,可以快速验证:
# 启动一个干净的 Ubuntu 容器,注意不同的系统版本可能有所区别
docker run -it --rm ubuntu:22.04
# 安装 systemd(部分镜像需手动)
apt update && apt install -y systemd
# 创建测试配置
echo 'd /tmp/testdir 0755 root root -' > /etc/tmpfiles.d/test.conf
# 执行 create(无 --dry-run,但容器可随意销毁)
systemd-tmpfiles --create
# 检查结果
ls -ld /tmp/testdir
容器即用即毁,完美模拟"dry-run"环境。
总结
| 问题 | 答案 |
|---|---|
| tmpfiles.d 有什么用? | 声明式管理临时文件/目录的生命周期 |
| 谁来执行? | systemd-tmpfiles-setup.service(启动时) + systemd-tmpfiles-clean.timer(每日清理) |
| 如何自定义? | 在 /etc/tmpfiles.d/ 放 .conf 文件 |
| 最常用类型? | d(创建目录)、q(安全清理)、x/X(排除路径) |
| 能替代什么? | 替代 rc.local 中的 mkdir -p /run/xxx、chmod 等操作 |
/tmp目录的作用和特点
/tmp目录的相关问题有时候在面试中会遇到,我们做一个大致了解。/tmp 目录是 Linux 和 Unix 系统中一个标准、关键且具有特殊语义的临时文件存储位置。它的设计和行为直接影响系统稳定性、安全性和应用程序兼容性。
一、核心作用
✅ 1. 供程序存放临时文件
- 编译器(如 gcc)生成的中间文件
- 解压工具(如 unzip)的临时工作区
- Web 服务器(如 PHP、Nginx)的会话或缓存文件
- 脚本运行时的临时数据交换
✅ 2. 进程间通信(IPC)的共享空间 - 通过在 /tmp 创建命名管道(FIFO)、socket 文件实现进程通信
- 例如:/tmp/.X11-unix/ 存放 X11 图形界面 socket
✅ 3. 符合 POSIX / FHS 标准 - Filesystem Hierarchy Standard (FHS) 明确规定:
"/tmp 是供所有用户和程序存放临时文件的目录,任何文件都可能被删除。"
二、关键特点
| 特点 | 说明 |
|---|---|
| 全局可写 | 默认权限 1777(drwxrwxrwt): 所有用户可读写- sticky bit (t); 用户只能删除自己创建的文件 |
| 生命周期短 | 文件通常不会跨系统重启保留: 很多发行版将 /tmp 挂载为 tmpfs(内存文件系统);即使是磁盘,也会被定期清理(如 systemd 的 tmpfiles.d) |
| 无持久性保证 | 程序不能依赖 /tmp 中的文件长期存在:系统可能随时清理; 掉电即丢失(若为 tmpfs) |
| 性能高 | 若挂载为 tmpfs,读写速度接近内存,适合高频临时操作 |
| 安全风险高 | 因全局可写,易受 symlink 攻击、竞争条件攻击→ 程序应使用 mktemp、mkdtemp 安全创建临时文件 |
三、典型实现方式
方式 1:tmpfs(内存文件系统)------ 推荐
xml
# 查看是否为 tmpfs
df -T /tmp
# 输出示例:
# tmpfs tmpfs 2G 0 2G 0% /tmp
- 优点:速度快、自动释放内存、重启清空
- 缺点:占用 RAM,大文件可能导致 OOM
方式 2:普通磁盘目录
- 常见于旧系统或嵌入式设备
- 需依赖 cron 或 systemd-tmpfiles 定期清理
四、自动清理机制(以 systemd 为例)
现代 Linux(使用 systemd)通过 tmpfiles.d 管理 /tmp:
xml
# /usr/lib/tmpfiles.d/tmp.conf
q /tmp 1777 root root 10d
- 每天由 systemd-tmpfiles-clean.timer 执行
- 删除 /tmp 中 10 天内未访问(atime)或未修改(mtime) 的文件
- 注意:正在使用的文件(如被进程打开)不会被删除
💡 即使文件被删,只要进程仍持有文件描述符,仍可读写(Linux 的"unlink but not close"特性)。
五、常见误区与最佳实践
| 误区 | 正确做法 |
|---|---|
| ❌ 把重要数据存 /tmp | ✅ 重要数据用 /var/lib/ 或用户家目录 |
| ❌ 手动 rm -rf /tmp/* 清理 | ✅ 用 systemd-tmpfiles --clean 或信任自动机制 |
| ❌ 在脚本中硬编码 /tmp/myfile | ✅ 使用 mktemp:TMPFILE=$(mktemp) |
| ❌ 认为 /tmp 永远是磁盘 | ✅ 检查 df -T /tmp,可能是内存 |
✅ 安全创建临时文件(Shell 示例)
xml
# 安全!自动创建唯一文件名,避免竞争条件
TMPFILE=$(mktemp) || exit 1
echo "data" > "$TMPFILE"
# ... 使用 ...
rm -f "$TMPFILE"
✅ 安全创建临时目录(Shell)
xml
TMPDIR=$(mktemp -d) || exit 1
trap 'rm -rf "$TMPDIR"' EXIT # 确保退出时清理
六、/tmp vs /var/tmp
| 特性 | /tmp | /var/tmp |
|---|---|---|
| 生命周期 | 通常不跨重启(不用重启也会定期清理) | 跨重启保留 |
| 清理周期 | 短(如 10 天) | 长(如 30 天) |
| 用途 | 短期临时文件 | 需要持久一点的临时数据(如安装包缓存) |
| FHS规定 | 可能被清空 | 应保留较长时间 |
💡 如果你的程序需要临时文件在重启后仍存在(如断点续传),应使用 /var/tmp。
七、安全加固建议
挂载时加 noexec,nosuid,nodev(防止执行恶意代码):
xml
# /etc/fstab
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev 0 0
限制大小(防 DoS):
xml
tmpfs /tmp tmpfs size=2G,noexec,nosuid,nodev 0 0
禁用 sticky bit 以外的权限继承(可选)
八、总结
| 项目 | 说明 |
|---|---|
| 用途 | 存放短期临时文件,供所有用户和程序使用 |
| 权限 | 1777(sticky bit 保护) |
| 生命周期 | 通常不跨重启,定期自动清理 |
| 存储介质 | 常为内存(tmpfs),速度快但易失 |
| 安全要求 | 程序必须使用 mktemp 等安全 API |
| 替代方案 | 长期临时文件 → /var/tmp;私有临时空间 → PrivateTmp=yes(systemd) |
总之记住:
"/tmp is temporary --- treat it as volatile."
(/tmp 是临时的------请视其为易失存储。)
更多关于运维的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出