Systemd 有一个很好的功能,即私有临时目录 ( /tmp
)。但从厚厚的手册中无法清楚了解正确的使用方法以及实现陷阱(感觉手册更像是开发人员和贡献者的规范)
启用此设置的副作用是添加
Requires=
和对访问和After=
所需的所有挂载单元的依赖关系。/tmp
/var/tmp
从https://www.freedesktop.org/software/systemd/man/systemd.exec.html#PrivateTmp=
对于非 systemd 内部人员来说,这有点难以理解。我假设我的文件系统(为了简单起见,假设我只有)/
将收到一个Requires=
,我想这可以留作练习,弄清楚它需要什么……也许我应该在这里放上家庭作业标签?:)
开始于https://www.freedesktop.org/software/systemd/man/systemd.mount.html#x-systemd.requires=
但这听起来不对。它说安装单元上的 Requires= 仅适用于层次结构。我猜。
让我们继续https://www.freedesktop.org/software/systemd/man/systemd.unit.html#Requires=
但这也没有解释任何事情。它只是说一个单元可能需要另一个单元。我猜。
我(大胆地)猜测它使用https://www.freedesktop.org/software/systemd/man/systemd.exec.html#ReadWritePaths=因此,在我的示例中,systemd 单元挂载/
将有一个Requires=[BindPaths=[/tmp/systemd-noise,/tmp]]
,或者无论如何在 systemd-speak 中写入它?
询问 systemd
# systemctl show httpd
...
Requires=system.slice sysinit.target -.mount tmp.mount
...
RequiresMountsFor=/tmp /var/tmp
也没什么帮助。
我主要想思考的是:
systemd 究竟是如何拒绝访问
/tmp
文件系统的。该进程(比如说从 systemd 启动的 apache 运行的 cgi)如何找出它
/tmp
可以访问的位置?
编辑:
这个问题来自 2020 年,当时 systemd 刚刚开始并为所有服务启用私有 tmp,除了“它使用文件系统命名空间和绑定挂载”之外,没有太多设置或文档。
现在在 2023 年我们确实有更多的设置来控制它PrivateTmp=
,但文档仍然只提到高级命名空间:)
我将保留这个问题,以防有人想深入研究源代码并记录实现陷阱
答案1
systemd 究竟如何拒绝访问文件系统上的实际 /tmp。
事实上并非如此。它只是/tmp
从流程的角度“替代”了。
它在路径/tmp
与全局目录不同的挂载命名空间中运行进程/tmp
。您可以使用以下命令序列自行执行此操作:
# run a shell in a new mount namespace
unshare -m
# create an empty directory
mkdir /tmp/my-private-tmp
# bind mount that directory on /tmp
mount -o bind /tmp/my-private-tmp /tmp
运行这些命令后,在同一个 shell 中查看一下/tmp
,你会发现它是空的:
# ls /tmp
total 0
在以下位置创建文件/tmp
:
touch /tmp/testfile
从不同的终端,你会看到这实际上是在创建的/tmp/my-private-tmp
:
# ls -l /tmp/my-private-tmp
从不同的终端,你会看到这实际上是在创建的/tmp/my-private-tmp
:
total 0
-rw-r--r-- 1 root root 0 Aug 27 21:53 testfile
该进程(假设从 systemd 启动的 Apache 运行的 CGI)如何找出它可以访问的 /tmp 在哪里?
它只是使用/tmp
。它不需要知道实际目录位于何处。
有关此主题的更多阅读内容:
systemd 如何决定新的 tmp 位置?
/tmp
它会在名为...的目录中创建子目录systemd-private-<something>-<unit>-<random hash>
,但我认为这与此无关。只需说“systemd 会为服务创建一个随机命名的目录”即可。
什么时候决定、什么时候创建,如果不是每个实例的短暂创建的话?
该目录在服务启动时创建。
怎么清洁?
服务停止时,目录将被删除。systemd.exec
手册页中写道:
服务停止后,这些目录中服务创建的所有临时文件都将被删除。
它是否尊重 systemd-tmpfiles 命令?
不,也不应该。systemd-tmpfiles 用于在系统启动时创建临时文件/目录。
如何在两个服务之间共享半私有 tmp?
从手册页中:
可以使用 JoinsNamespaceOf= 指令在同一个私有 /tmp/ 和 /var/tmp/ 命名空间内运行两个或多个单元,有关详细信息,请参阅 systemd.unit(5)。