systemd之PrivateTmp
主机上根目录占用满,发现是/tmp目录下某个文件夹(mariadb)占用空间大,但是文件夹命名比较奇怪:
ll
...
rwx------ 3 root root 4096 Mar 15 20:26 systemd-private-e153918a94a74296867771449bc394a8-mariadb.service-mPLdEr
drwx------ 3 root root 4096 Mar 15 21:29 systemd-private-e153918a94a74296867771449bc394a8-neutron-openvswitch-agent.service-Z6DIf6
drwx------ 3 root root 4096 Mar 15 23:55 systemd-private-e153918a94a74296867771449bc394a8-neutron-server.service-jNN2Cp
...
问题环境
主机:CentOS Linux release 7.7.1908 (Core)
问题分析
文件夹命令遵循一定的规则,因此不像是人为创建,由于是systemd开头,所以还是从systemd入手查询相关的资料,得知:
托管于systemd的服务启用了安全Tmp系统功能。
vim /usr/lib/systemd/system/mariadb.service
...
UMask=007
# Give a reasonable amount of time for the server to start up/shut down
TimeoutSec=600
# Place temp files in a secure directory, not /tmp
PrivateTmp=true
LimitNOFILE=65535
LimitNPROC=65535
...
在service配置文件中可以看到PrivateTmp=true此选项,表示开启了安全Tmp系统功能。
PrivateTmp
用英文看比较明了
--PrivateTmp
Takes a boolean argument. If true, sets up a new file system namespace for the executed processes and mounts private /tmp/ and /var/tmp/ directories inside it that are not shared by processes outside of the namespace.This is useful to secure access to temporary files of the process, but makes sharing between processes via /tmp/ or /var/tmp/ impossible. If true, all temporary files created by a service in these directories will be removed after the service is stopped.
作用
1、/tmp目录以及/var/tmp目录所有进程都在公用,不够安全,使用PrivateTmp后,进程用于自己的独立的目录以及相应的权限
2、关于目录的管理托管于systemd,即当systemd进程启动时会建立相应的目录(目录会在两个地方建立,/tmp以及/var/tmp/下建立两个目录),当通用systemd进程关闭时会删除相应的目录,不用程序单独处理
原理
在上述说明中也可以看到,开启选项后,会为进程创造单独的namespace,然后会把/tmp/以及/var/tmp/挂载到新建的目录中。即开启mnt命名空间,然后执行挂载。
cd /proc/41252(主进程号)
cat mountinfo |grep tmp
...
165 131 8:2 /tmp/systemd-private-e153918a94a74296867771449bc394a8-mariadb.service-mPLdEr/tmp /tmp rw,relatime shared:145 master:1 - ext4 /dev/sda2 rw,data=ordered
166 131 8:2 /var/tmp/systemd-private-e153918a94a74296867771449bc394a8-mariadb.service-k8LOj8/tmp /var/tmp rw,relatime shared:146 master:1 - ext4 /dev/sda2 rw,data=ordered
...
当然也可以用nsenter登陆验证
nsenter -t 41252 -m
//可以看到此处只能看到自己的挂载点的文件,而不是主机上的/tmp,/var/tmp同样如此
cd /tmp
程序使用
由于使用了命名空间挂载,所以对于程序本身来说么不需要更改任何东西,但是对于其他进程来说,如果要读取改进程的临时文件,则需要注意临时文件的路径,而不是直接读取/tmp或者/var/tmp下目录,而是主机上systemd新建的目录
tmpfiles.d
其实/tmp下目录并不是永久存储的,有可能会被删除,那么PrivateTmp会不会被系统自动删除(非进程本身),从而影响正在运行的进程?这牵扯到tmpfiles.d(临时文件管理系统)。
tmpfiles.d
配置文件定义了一套临时文件管理机制: 创建 文件、目录、管道、设备节点, 调整 访问模式、所有者、属性、限额、内容, 删除 过期文件。 主要用于管理易变的临时文件与目录,例如 /run
, /tmp
, /var/tmp
, /sys
, /proc
, 以及 /var
下面的某些目录。
systemd-tmpfiles 根据这些配置, 在系统启动过程中创建易变的临时文件与目录,并在系统运行过程中进行周期性的清理。牵扯 systemd-tmpfiles-setup.service
, systemd-tmpfiles-cleanup.service
等相关服务。
systemd-tmpfiles-clean.service服务
服务何时被执行呢?
Linux下该服务的执行可以根据systemd-tmpfiles-clean.timer进行管理
[root@sam01 ~]# cat /usr/lib/systemd/system/systemd-tmpfiles-clean.timer
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Daily Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
[Timer]
OnBootSec=15min
OnUnitActiveSec=1d
# OnBootSec 表示相对于机器被启动的时间点
# 表示相对于匹配单元(本标签下Unit=指定的单元)最后一次被启动的时间点
上述配置文件表示两种情况会执行该服务
- 开机15分钟执行服务
- 距离上次执行该服务1天后执行服务
服务如何执行呢?
[root@sam01 ~]# cat /usr/lib/systemd/system/systemd-tmpfiles-clean.service
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Cleanup of Temporary Directories
Documentation=man:tmpfiles.d(5) man:systemd-tmpfiles(8)
DefaultDependencies=no
Conflicts=shutdown.target
After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target time-sync.target
Before=shutdown.target
[Service]
Type=oneshot
ExecStart=/usr/bin/systemd-tmpfiles --clean
IOSchedulingClass=idle
# Type=oneshot 这一选项适用于只执行一项任务、随后立即退出的服务
# 命令文件 /usr/bin/systemd-tmpfiles
# 命令参数 --clean
# 通过定期执行 /usr/bin/systemd-tmpfiles --clean 完成清理
命令: /usr/bin/systemd-tmpfiles
[root@cdpm03 41252]# /usr/bin/systemd-tmpfiles --help
systemd-tmpfiles [OPTIONS...] [CONFIGURATION FILE...]
Creates, deletes and cleans up volatile and temporary files and directories.
-h --help Show this help
--version Show package version
--create Create marked files/directories
--clean Clean up marked directories
--remove Remove marked files/directories
--boot Execute actions only safe at boot
--prefix=PATH Only apply rules with the specified prefix
--exclude-prefix=PATH Ignore rules with the specified prefix
--root=PATH Operate on an alternate filesystem root
哪些目录被标记,又是什么样的标记呢?
这些都在配置文件中定义:对于不同目录下的同名配置文件,仅以优先级最高的目录中的那一个为准。具体说来就是: /etc/tmpfiles.d
的优先级最高、 /run/tmpfiles.d
的优先级居中、 /usr/lib/tmpfiles.d
的优先级最低。 软件包应该将自带的配置文件安装在 /usr/lib/tmpfiles.d
目录中, 而 /etc/tmpfiles.d
目录仅供系统管理员使用。
/tmp以及/var/tmp管理
/tmp以及/var/tmp的目录规则定义在 /usr/lib/tmpfiles.d/tmp.conf中:
vim /usr/lib/tmpfiles.d/tmp.conf
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
# See tmpfiles.d(5) for details
# Clear tmp directories separately, to make them easier to override
# 类型, 路径, 权限, 属主, 属组, 寿命, 参数
v /tmp 1777 root root 10d
v /var/tmp 1777 root root 30d
# Exclude namespace mountpoints created with PrivateTmp=yes
x /tmp/systemd-private-%b-*
X /tmp/systemd-private-%b-*/tmp
x /var/tmp/systemd-private-%b-*
X /var/tmp/systemd-private-%b-*/tmp
上述配置表示:
- 清理/tmp目录超过10天的内容,但是匹配/tmp/systemd-private-%b-*的目录及其路径下的全部内容会被保留
- 清理/var/tmp目录超过30天的内容,但是匹配/var/tmp/systemd-private-%b-*的目录及其路径下的全部内容被保留
即排除了systemd进程创建的目录,由systemd自己来管理,从而避免了误删除正在运行程序的临时文件夹。
过期时间
“寿命”是根据对象的最后修改时间(mtime)、 最后访问时间(atime)、 最后状态变化时间(ctime)(目录除外) 计算的。 如果三者(或两者)中最晚的时间与当前系统时间之差大于”寿命”字段的值, 那么该对象就会被删除, 否则该对象将会被保留。
权限问题
清理临时文件中文件其实有个小小的bug,即所有清理的文件root用户必须有w权限,否则不能删除
cd /tmp
ll
-r-xrwxrwx 1 root root 0 Mar 8 04:00 1.txt
/usr/bin/systemd-tmpfiles --clean
ll
-r-xrwxrwx 1 root root 0 Mar 8 04:00 1.txt
参考文档