tmp目录
首先看下FHS的定义。
FHS(Filessystem Hierarchy Standard) 的重点在于规范每个特定的目录下应该要放置什么样子的数据。
tmp约定的存放内容
/tmp 这是让一般用户或者正在执行的程序暂时放置文件的地方。这个目录是任何人都能够访问,所以你需要定期清理一下。当然,重要数据不可放置在此目录。因为FHS甚至建议在开机时,应该要将/tmp下的数据都删除
清理方式
不同的 Linux 发行版其实对 /tmp 目录的清理方式有所不同:
· 在 Debian-like 的系统,启动的时候才会清理 (规则定义在 /etc/default/rcS )
· 在 RedHat-like 的系统,按文件存在时间定时清理 (RHEL6 规则定义在 /etc/cron.daily/tmpwatch ; RHEL7 以及 RedHat-like with systemd 规则定义在 /usr/lib/tmpfiles.d/tmp.conf , 通过 systemd-tmpfiles-clean.service 服务调用)
· 在 CentOS 里,也是按文件存在时间清理的 (通过 crontab 的配置 /etc/cron.daily 定时执行 tmpwatch 来实现)
· 在 Gentoo 里也是启动清理,规则定义在 /etc/conf.d/bootmisc
tmpwatch
例子
flags=-umc /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix \ -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix \ -X ‘/tmp/hsperfdata_*’ 10d /tmp
语法
-u, --atime 基于访问时间来删除文件,默认的。
-m, --mtime 基于修改时间来删除文件。
-c, --ctime 基于创建时间来删除文件,对于目录,基于mtime。
-M, --dirmtime 删除目录基于目录的修改时间而不是访问时间。
-a, --all 删除所有的文件类型,不只是普通文件,符号链接和目录。
-d, --nodirs 不尝试删除目录,即使是空目录。
-d, --nosymlinks 不尝试删除符号链接。
-f, --force 强制删除。
-q, --quiet 只报告错误信息。
-s, --fuser 如果文件已经是打开状态在删除前,尝试使用“定影”命令。默认不启用。
-t, --test 仅作测试,并不真的删除文件或目录。
-U, --exclude-user=user 不删除属于谁的文件。
-v, --verbose 打印详细信息。
-x, --exclude=path 排除路径,如果路径是一个目录,它包含的所有文件被排除了。如果路径不存在,它必须是一个绝对路径不包含符号链接。
-X, --exclude-pattern=pattern 排除某规则下的路径。
crontab定时
cron工具是一个以系统服务的形式存在。通过/etc/rc.d/init.d 或者 /etc/init.d目录下的启动脚本crond来启动。 也可能直接通过 service crond start 命令来启动。
cron不停地检查所有配置的任务在当前是否应该运行,任务运行的最小时间间隔是1分钟,也就是说任务最频繁只能每分钟运行一次。
可用crontab -e命令来编辑,编辑的是/var/spool/cron下对应用户的cron文件,也可以直接修改/etc/crontab文件。具体格式如下:
Minute Hour Day Month Week command
分钟 小时 天 月 星期 命令
0-59 0-23 1-31 1-12 0-6 command
/var/log/cron 是crontab的日志
具体的配置参考如下的目录中的内容
/etc/cron.hourly
/etc/cron.daily
tmpfiles服务
系统使用systemd管理易变与临时文件,与之相关的系统服务有3个:
systemd-tmpfiles-setup.service :Create Volatile Files and Directories
systemd-tmpfiles-setup-dev.service:Create static device nodes in /dev
systemd-tmpfiles-clean.service :Cleanup of Temporary Directories
相关的配置文件也有3个地方:
/etc/tmpfiles.d/*.conf
/run/tmpfiles.d/*.conf
/usr/lib/tmpfiles.d/*.conf
/tmp目录的清理规则主要取决于/usr/lib/tmpfiles.d/tmp.conf文件的设定
对于不同目录下的同名配置文件, 仅以优先级最高的目录中的那一个为准。 具体说来就是: /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), 如果想要创建简单的配额组层次关系, 那么应该使用下面的q
或Q
。 -
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), 同时,新建子卷的叶子配额组也会分配给它(中间配额组)。单就新建子卷自身而言,q
与Q
在实际效果上并无不同, 但是通过插入一个新的 higher-level 配额组,Q
可以实现对该新建的子卷以及 未来创建在该子卷之下的下级子卷进行统一的配额限制。 这样,在通过q
与Q
创建子卷的同时,也一起实现了一颗"配额子树"。 每一个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风格的通配符。 注意,这个保护措施对
r
与R
无效。 -
X
在根据"寿命"字段清理过期文件时, 仅忽略指定的路径自身而不包括该路径下的其他内容。 可以在"路径"字段中使用shell风格的通配符。 注意,这个保护措施对
r
与R
无效。 -
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)。 但对于 z
与 Z
来说,省略或者设为 "-
" 则表示不修改现有的"属主"与"属组"。 此字段对于 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/
下的所有内容。即使此目录不存在也不会创建它。