如何使用 systemd 私有临时目录功能?

如何使用 systemd 私有临时目录功能?

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

也没什么帮助。

我主要想思考的是:

  1. systemd 究竟是如何拒绝访问/tmp文件系统的。

  2. 该进程(比如说从 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)。

相关内容