tmpfiles.d 中文手册

译者:金步国


版权声明

本文译者是一位开源理念的坚定支持者,所以本文虽然不是软件,但是遵照开源的精神发布。

其他作品

本文译者十分愿意与他人分享劳动成果,如果你对我的其他翻译作品或者技术文章有兴趣,可以在如下位置查看现有的作品集:

联系方式

由于译者水平有限,因此不能保证译文内容准确无误。如果你发现了译文中的错误(哪怕是错别字也好),请来信指出,任何提高译文质量的建议我都将虚心接纳。


手册索引 . 指令索引systemd-235

名称

tmpfiles.d — 配置如何创建、删除、清理易变文件与临时文件

大纲

/etc/tmpfiles.d/*.conf

/run/tmpfiles.d/*.conf

/usr/lib/tmpfiles.d/*.conf

描述

systemd-tmpfiles 使用上述三个目录中的配置文件 来决定如何创建、删除、清理 易变文件与临时文件以及易变目录与临时目录。

这些文件与目录通常位于 /run, /var/run(指向 /run 的软连接), /tmp, /var/tmp, /sys, /proc, /var 目录中。

系统的守护进程经常需要在 /run 目录下拥有专属的运行时目录,以存放套接字或管道之类的文件。 对于这个目的,应该使用单元文件中的 RuntimeDirectory= 选项(参见 systemd.exec(5) 手册)。

配置目录及其优先级

配置文件的名称必须符合 package.confpackage-part.conf 格式。 当需要明确的将某部分(part)配置提取出来,以方便用户专门针对这部分进行修改的时候, 应该使用第二种命名格式。

对于不同目录下的同名配置文件, 仅以优先级最高的目录中的那一个为准。 具体说来就是: /etc/ 的优先级最高、 /run/ 的优先级居中、 /usr/lib/ 的优先级最低。 软件包应该将自带的配置文件安装在 /usr/lib/ 目录中, 而 /etc/ 目录仅供系统管理员使用。 所有的配置文件,无论其位于哪个目录中,都统一按照文件名的字典顺序处理。 如果在多个配置文件中设置了同一个路径(文件或目录), 那么仅以文件名最靠前(字典顺序)的那一个为准, 其他针对同一个路径的配置项将会作为警告信息记录到错误日志中。 如果有两行互为前后缀, 那么始终是先处理前缀、再处理后缀。 所有带有shell风格通配符的行, 都在所有不带通配符的行之后处理。 如果有多个操作符应用于同一个文件(例如 ACL, xattr, 文件属性调整), 那么将始终按固定的顺序操作。 对于其他情况, 文件与目录总是按照它们在配置文件中出现的顺序处理。

如果系统管理员想要屏蔽 /usr/lib/ 目录中的某个配置文件, 那么最佳做法是在 /etc/ 目录中 创建一个指向 /dev/null 的同名符号链接, 即可彻底屏蔽 /usr/lib/ 目录中的同名文件。

配置文件格式

配置文件的格式是每行对应一个路径,包含如下字段: 类型, 路径, 权限, 属主, 属组, 寿命, 参数

#Type Path        Mode UID  GID  Age Argument
d     /run/user   0755 root root 10d -
L     /tmp/foobar -    -    -    -   /dev/null

字段值可以用引号界定,并可以包含C风格的转义字符。

类型(Type)

"类型"字段由一个单独的、表示类型的字母与一个可选的感叹号(!)组成。

可以识别的类型如下:

f

若指定的文件不存在,则创建它,否则什么也不做。 若设置了"参数"字段,则将其内容写入指定的文件。 不追踪软连接。

F

若指定的文件不存在,则创建它,否则清空已有文件。 若设置了"参数"字段,则将其内容写入指定的文件。不追踪软连接。

w

若指定的文件存在,则将"参数"字段的内容写入该文件,否则什么也不做。 注意:不会在"参数"字段内容的末尾添加额外的换行符, 可以在"参数"字段中使用C语言风格的转义字符。 可以在"路径"字段中使用shell风格的通配符。 追踪软连接。

d

创建指定的目录并赋于指定的UID/GID与权限。 如果指定的目录已经存在,那么仅调整UID/GID与权限。 如果指定了"寿命"字段,那么该目录中的内容将遵守基于时间的清理策略。

D

d 类似, 但是如果使用了 --remove 选项,那么将会清空目录中的所有内容。

e

d 类似,但是并不创建原本不存在的目录。 可以在"路径"字段中使用shell风格的通配符。 要想让此类型有效,必须至少明确设置 权限, 属主, 属组, 寿命 字段之一。 如果"寿命"字段的值为 "0" , 那么每次运行 systemd-tmpfiles --clean 命令都会无条件的清空该目录。 这个特性经常与 ! 一起使用(参见后文的"例子"小节)。

v

如果指定的路径不存在, 并且该路径位于一个Btrfs子卷中, 那么按照指定的路径创建子卷。 否则,创建一个普通的目录(与 d 一样)。 仅对Btrfs文件系统有意义。 此处创建的子卷不会被分配给任何 higher-level 配额组(quota group), 如果想要创建简单的配额组层次关系, 那么应该使用下面的 qQ

q

v 类似, 但会将所创建的新子卷分配给父子卷(父目录) 所属的 higher-level 配额组(quota group)。 这样可以确保作用于父子卷(父目录)的 higher-level 配额组 可以包含此处创建的新子卷(子目录)。 仅对Btrfs文件系统有意义, 在非Btrfs文件系统上与 d 等价。 如果指定的子卷(路径)已经存在, 并且已经被分配给了一个或多个 higher-level 配额组,那么不修改任何现有的配额层次关系。 参见下面的 Q 以及 btrfs-qgroup(8) 手册,以了解更多关于btrfs的配额组(quota group)的概念。

Q

q 类似, 但并不直接复用父子卷(父目录)的 higher-level 配额组(quota group), 而是首先找到父子卷(父目录)的 最低级非叶子配额组(也就是倒数第二级配额组), 然后在此配额组与最末端的叶子配额组之间, 插入一个level值减一的"中间配额组", 并且与新建的子卷共享同一个ID。 如果父子卷(父目录)不存在 higher-level 配额组, 那么插入一个level值为255且ID与新建子卷相同的"中间配额组", 并且这个新建的"中间配额组"将被指定为 父子卷(父目录)的 higher-level 配额组(quota group), 同时,新建子卷的叶子配额组也会分配给它(中间配额组)。

单就新建子卷自身而言, qQ 在实际效果上并无不同, 但是通过插入一个新的 higher-level 配额组, Q 可以实现对该新建的子卷以及 未来创建在该子卷之下的下级子卷进行统一的配额限制。 这样,在通过 qQ 创建子卷的同时,也一起实现了一颗"配额子树"。 每一个 Q 创建的子卷都将拥有一个自己专属的配额层次结构(配额子树), 可用于容纳将来创建的下级子卷。 每一个 q 创建的子卷都没有自己专属的配额子树, 其自身会被添加到直属父子卷(父目录)所属的配额子树中。

Q 通常用于 /home/var/lib/machines 这样的目录, 其特点是: 不但需要包含多个下级子卷, 而且需要将所有下级子卷视为一个整体进行配额限制。 q 通常用于 /var/var/tmp 这样的目录, 其特点是: 要么不需要包含下级子卷, 要么不需要将所有下级子卷视为一个整体进行配额限制。 与 q 一样,Q 也不会改变任何已经存在的配额层次关系,也就是说, 如果指定的子卷(路径)已经存在,并且已经被分配给了一个或多个 higher-level 配额组, 那么不修改任何现有的配额层次关系。

p, p+

若指定的管道(FIFO)不存在,则创建它,否则什么也不做。 后缀 + 表示:若指定的路径已存在一个非管道文件, 则先删除此文件再创建指定的管道文件。

L, L+

若指定的软连接不存在,则创建它,否则什么也不做。 后缀 + 表示: 若指定的路径已存在一个非软连接文件或目录, 则先删除此文件或目录再创建指定的软连接。 若"参数"字段为空, 那么将创建一个指向 /usr/share/factory/ 目录中同名文件的软连接。 注意,软连接的UID/GID与权限将被忽略。

c, c+

若指定的字符设备不存在,则创建它,否则什么也不做。 后缀 + 表示: 若指定的路径已存在一个非字符设备的文件, 则先删除此文件再创建指定的字符设备。 因为udev并不管理运行时创建的静态设备节点, 所以建议在末尾加上"!",以确保仅在系统启动期间才创建此静态设备节点。

b, b+

若指定的块设备不存在,则创建它,否则什么也不做。 后缀 + 表示: 若指定的路径已存在一个非块设备的文件, 则先删除此文件再创建指定的块设备。 因为udev并不管理在运行时创建的静态设备节点, 所以建议在末尾加上"!",以确保仅在系统启动期间才创建此静态设备节点。

C

若指定的文件或目录不存在, 则递归的从"参数"字段所指定的文件或目录复制, 否则什么也不做。 若"参数"字段为空, 那么将从 /usr/share/factory/ 目录中 递归的复制同名文件或目录。 不追踪软连接。

x

在根据"寿命"字段清理过期文件时, 忽略指定的路径及该路径下的所有内容。 可以在"路径"字段中使用shell风格的通配符。 注意,这个保护措施对 rR 无效。

X

在根据"寿命"字段清理过期文件时, 仅忽略指定的路径自身而不包括该路径下的其他内容。 可以在"路径"字段中使用shell风格的通配符。 注意,这个保护措施对 rR 无效。

r

若指定的文件或目录存在,则删除它。 不可用于非空目录。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

R

若指定的文件或目录存在,则递归的删除它。 可用于非空目录。可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

z

若指定的文件或目录存在, 则仅设置其自身的访问权限、属主、属组、重置SELinux安全上下文。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

Z

若指定的文件或目录存在, 则递归的设置其访问权限、属主、属组、重置SELinux安全上下文。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

t

若指定的文件或目录存在, 则仅设置其自身的SMACK标签。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

T

若指定的文件或目录存在, 则递归的设置其SMACK标签。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。

h

若指定的文件或目录存在,则仅调整其自身的属性。 可以在"路径"字段中使用shell风格的通配符。

"参数"字段的格式是 [+-=][aAcCdDeijsStTu] , 具体解释如下: + 前缀表示添加属性(这是默认值); - 前缀表示去除属性; = 前缀表示设置属性(但对 "aAcCdDeijsStTu" 范围之外的其他属性没有影响); 而后缀字母 "aAcCdDeijsStTu" 则用于表示各种属性, 其含义与 chattr(1) 手册里的解释一致。

注意,将"参数"字段设为一个单独的 =(无后继字母) 表示重置所有 "aAcCdDeijsStTu" 代表的属性。 不追踪软连接。

H

若指定的文件或目录存在,则递归的调整其属性。 可以在"路径"字段中使用shell风格的通配符。 不追踪软连接。"参数"字段的语法与 h 完全相同。

a, a+

若指定的文件或目录存在, 则仅设置其自身的访问控制列表(POSIX ACL)。 可以在"路径"字段中使用shell风格的通配符。 后缀 + 表示将指定的项添加到已有的访问控制列表中。 除非基本权限已经存在或被明确指定, 否则 systemd-tmpfiles 将会自动根据"权限","属主","属组"字段添加所需的基本权限。 如果没有明确指定访问控制列表或者访问控制列表已经存在, 那么将会叠加上掩码。 不追踪软连接。

A, A+

若指定的文件或目录存在,则递归的设置访问控制列表(POSIX ACL)。 其他与 a/a+ 完全相同。 不追踪软连接。

使用了感叹号(!)标记的行,仅可用于系统启动过程中, 禁止用于运行中的系统(会破坏系统的正常运行)。 未使用感叹号(!)标记的行, 可以在任意时间安全的执行(例如升级软件包的时候)。 systemd-tmpfiles 仅在明确使用了 --boot 选项的时候才会执行使用了感叹号(!)标记的行。

例如:

# 确保默认创建此目录
d /tmp/.X11-unix 1777 root root 10d

# 仅在系统启动时清理X11的锁文件(但在运行时禁止删除这些文件)
r! /tmp/.X[0-9]*-lock

本例中的第二行仅在明确使用了 --boot 选项的时候才会执行, 因为它会破坏正在运行中的系统。 但是第一行则无此限制,可以在任何时候执行都不会对系统造成损害。

路径(Path)

"路径"字段是指文件系统路径, 并且支持几个简单的替换标记:

表 1. 可用于替换的标记

标记含义解释
"%m"Machine ID系统的"Machine ID"字符串。参见 machine-id(5) 手册。
"%b"Boot ID系统的"Boot ID"字符串。参见 random(4) 手册。
"%H"Host name系统的主机名(hostname)
"%v"Kernel release内核版本(uname -r 的输出)
"%%"Escaped %百分号自身(%)。使用"%%"表示一个真正的"%"字符。

权限(Mode)

"权限"字段表示设置文件或目录的权限, 如果省略或设为 "-" 则表示使用默认权限, 也就是:对于目录使用"0755"、对于文件使用"0644", 但对于 z, Z 表示不修改现有的权限。 此字段对于 x, r, R, L, t, a 没有意义。

可选前缀 "~" 的含义是掩码, 也就是将此字段当作权限掩码来使用。 换句话说,就是将此字段设置的值与现有的权限做"位与"运算。 举例来说,假设原有文件的权限是"0765",此字段的值是"~1550", 那么文件的最终权限将是"0540"。 如果省略了 sticky/SUID/SGID 位, 那么对于文件来说相当于全部清除, 而对于目录来说则相当于保持不变。 例如"~550",对于文件来说相当于"~0550", 而对于目录来说则相当于"~7550"。 此特性在实践中仅对 Z 有实际价值。

属主,属组(UID,GID)

"属主"与"属组"字段分别表示文件或目录的所属用户与所属用户组。 可以设为数字形式的UID/GIU值,也可以设为字符串形式的用户名称/组名称。 如果省略或者设为 "-" 则表示使用默认值"0"(root)。 但对于 zZ 来说,省略或者设为 "-" 则表示不修改现有的"属主"与"属组"。 此字段对于 x, r, R, L, t, a 没有意义。

寿命(Age)

"寿命"字段用于判定在清理过期文件或子目录时应该删除哪些, 也就是决定了文件或子目录的"寿命"。 如果文件或子目录的最后改动时间(ctime) 与当前系统时间之差已经大于"寿命"字段的值, 那么这些文件或子目录将被删除。 此字段的值是一个时间长度, 可以使用下面的时间单位后缀: us(微秒), ms(毫秒), s(秒), m(分), h(时), d(天), w(周)。

可以同时使用多个时间单位, 例如"5m10s"表示5分10秒(也就是310秒)。 如果省略了时间单位,那么表示使用默认单位"秒"。

如果将此字段设为数字"0", 那么表示在每次清理时都无条件的删除所有文件或子目录。

此字段仅对 d, D, e, v, q, Q, C, x, X 有意义。如果省略此字段或将其设为 "-" ,那么表示不进行任何清理。

如果此字段的值以 "~" 开头, 那么表示在每次清理时都无条件的保留指定目录直属的文件与子目录, 也就是仅清理直属子目录下的内容。

参数(Argument)

"参数"字段对不同的"类型"有不同的作用: 对于 L 来说,用于指定软连接的目标路径。 对于 c, b 来说, 用于以"主设备号:次设备号"的格式设定设备节点的主/次设备号(十进制整数), 例如 "1:3" 。 对于 f, F, w 来说, 用于设置一个写入文件的短字符串(实际写入时会在末尾附加一个换行符)。 对于 C 来说,用于指定源文件或者源目录。 对于 t, T 来说, 用于指定将要设置的扩展属性。 对于 a, A 来说,用于指定将要设置的ACL属性。 对于 h, H 来说,用于指定将要设置的文件属性。 对于其他类型无意义,将被忽略。

例子

例 1. 按照指定的UID/GID与权限创建目录

screen(1) 需要在系统启动时按照指定的属主/属组/权限创建两个目录

# /usr/lib/tmpfiles.d/screen.conf
d /run/screens  1777 root screen 10d
d /run/uscreens 0755 root screen 10d12h

/run/screens 中超过10天的内容将被清理。 /run/uscreens 中超过10.5天的内容将被清理。


例 2. 创建一个带有 SMACK 属性的目录

D /run/cups - - - -
t /run/cups - - - - security.SMACK64=printing user.attr-with-spaces="foo bar"
      

该目录的属主将是"root"并且会被赋予默认权限。 目录中的内容将不会被定期清理,但可使用 systemd-tmpfiles --remove 命令清除。


例 3. 创建一个不会被定期清理的目录

abrt(1) 需要在系统启动时按照指定的属主/属组/权限创建一个目录, 并且禁止清理 /var/tmp 目录

# /usr/lib/tmpfiles.d/tmp.conf
d /var/tmp 1777 root root 30d
# /usr/lib/tmpfiles.d/abrt.conf
d /var/tmp/abrt 0755 abrt abrt -

例 4. 启用系统启动过程中的清理,以及基于时间的清理

# /usr/lib/tmpfiles.d/dnf.conf
r! /var/cache/dnf/*/*/download_lock.pid
r! /var/cache/dnf/*/*/metadata_lock.pid
r! /var/lib/dnf/rpmdb_lock.pid
e  /var/cache/dnf/ - - - 30d

系统启动过程中将会清理 lock 文件。 /var/cache/dnf/ 目录中闲置超过30天的内容将会被删除。


例 5. 在启动时清空缓存目录

# /usr/lib/tmpfiles.d/krb5rcache.conf
e! /var/cache/krb5rcache - - - 0

在启动时清空 /var/cache/krb5rcache/ 下的所有内容。即使此目录不存在也不会创建它。


参见

systemd(1), systemd-tmpfiles(8), systemd-delta(1), systemd.exec(5), attr(5), getfattr(1), setfattr(1), setfacl(1), getfacl(1), chattr(1), btrfs-subvolume(8), btrfs-qgroup(8)