根据FHS-3.0,/tmp
用于临时文件,/run
用于运行时变量数据。/run
下次启动时必须删除in 中的数据,这对于 来说不是必需的/tmp
,但程序仍然不能假设 in 中的数据/tmp
在下次程序启动时可用。这一切似乎与我很相似。
那么,两者有什么区别呢?程序应根据什么标准决定是否将临时数据放入/tmp
或放入/run
?
根据 FHS 的数据:
程序可能有一个子目录
/run
;对于使用多个运行时文件的程序,鼓励这样做。
这表明“系统程序”和“普通程序”之间的区别不是标准,程序的生命周期也不是标准(例如,长时间运行的进程与短期运行的进程)。
尽管 FHS 中没有给出以下基本原理,但/run
引入它是为了克服安装得太晚的问题/var
,以致需要/var/run
尽早提供肮脏的技巧。然而,现在随着/run
和 的引入,并考虑到其在 FHS 中的描述,似乎没有明确的理由同时拥有/run
和/tmp
。
答案1
目录/tmp
和/usr/tmp
(后来的/var/tmp
)曾经是所有东西和每个人的垃圾场。这些目录中文件的唯一保护机制是粘性位,它限制其所有者删除或重命名其中的文件。正如 marcelm 在评论中指出的那样,原则上没有什么可以阻止某人创建具有服务所使用的名称的文件(例如nginx.pid
或sshd.pid
)。 (但实际上,启动脚本可以首先删除此类伪造文件。)
/run
是为长寿命服务的非持久运行时数据而建立的,例如锁、套接字、pid 文件等。由于它对公众不可写,因此它可以保护服务运行时数据免受混乱/tmp
和清理工作的影响。事实上:我运行的两个发行版(没有双关语)的权限为 755 /run
,而/tmp
和/var/tmp
(/dev/shm
就此而言)的权限为 1777。
答案2
/tmp
是创建临时文件和目录的位置。它不能用于存储“众所周知的名称”(即另一个进程可以知道的名称,而无需您以某种方式将名称传递给它),因为没有人拥有名称空间的所有权;任何人都可以在那里创建文件。因此,当您有一个实用程序需要文件(即不是管道等)作为输入或输出时,通常会使用它,只要您传入名称,任何(随机生成的)名称都将起作用。
从历史上看,有些东西(如 X)违反了这一原则,并将众所周知的名称(如.X11-unix
)放入/tmp
.这当然是有问题的,并且允许任何用户简单地通过首先按所需名称创建文件来 DoS 需要这样做的服务。此类内容属于/run
(或者/var/run
如果您不订阅 Freedesktop.org 修正主义则等同)。当然,更好的办法是修复它们,不要在全局命名空间中使用众所周知的名称,而是传递路径名。
答案3
没有理由同时拥有 /run 和 /tmp
我想你是正确的。 /tmp
现在我们已经基本上弃用了/run
.如果您的程序能够这样做(这要求它是已安装作为特权操作),那么现在您将使用/run
.这是出于安全原因。
例如,CUPS 打印守护程序不以 root 身份运行,但通常从操作系统软件包安装。该软件包安装/usr/lib/tmpfiles.d/cups.conf
并systemd-tmpfiles
创建一个可以访问的目录。由于该目录位于 下/run
,因此该名称不能被非特权用户恶意占用,/tmp
这与全局可写的目录不同。
不能/run
直接使用的“非特权程序”
真正的区别在于您的程序是否由任意非特权用户在其自己的用户 ID 下运行。但您通常仍然不想使用/tmp
,因为它可以被其他非特权用户访问。您更愿意使用$XDG_RUNTIME_DIR
.通常这是实现为/run/user/$(id -u)
- 所以它恰好/run
也是 的子目录。但位置并不能保证;程序应始终使用环境变量。
/tmp
仅对系统上不同非特权用户之间的临时合作有用。这种临时系统很容易受到拒绝合作并破坏每个人的事情的恶意用户的攻击:)。一个例子是非特权用户决定talk
使用 unix 套接字运行守护程序的一个版本。
原始资料 来自伦纳特·珀特林
请注意,下面的 Poettering 清单声称这/tmp
对于“小文件”有用,而/run
只能用于“通信原语”。我也不认为这种区别是正确的。的海报男孩/run
是udev
,我很确定/run/udev
包括内部数据库。一旦你有了一个/run
目录,我认为没有人愿意遵循所声称的区别并创建其他目录,混乱/tmp
。所以在实践中我们只是使用/run
now直播账号。
使用世界可写共享命名空间 [如 /tmp] 进行通信一直是有问题的,因为要建立通信,您需要稳定的名称,但稳定的名称为 DoS 攻击打开了大门。这可以通过在早期启动期间为某些服务建立受保护的每个应用程序目录来部分纠正(就像我们为 X11 所做的那样),但这只能部分解决问题,因为只有在每个软件包安装后都重新启动时才能正常工作。
...
Fedora 的另一个功能(针对 Fedora 17)通过隔离各种服务的 /tmp 命名空间,更改了许多系统服务的 /tmp 语义,使它们更加安全
...
因为 /tmp 不再一定是共享命名空间,所以它通常不适合作为通信原语的位置。
...
[/run] 保证是 tmpfs,因此在启动时会自动刷新。除此之外,不会进行任何自动清理。
...
以下是我们建议您(Linux 应用程序开发人员)如何选择正确的目录的粗略指南:
- 您需要一个地方来放置套接字(或其他通信原语)并且您的代码以特权运行:使用 /run 下的子目录。 (或者在 /var/run 下以获得额外的兼容性。)
- 您需要一个地方来放置套接字(或其他通信原语)并且您的代码以非特权方式运行:使用 $XDG_RUNTIME_DIR 下的子目录。
- 您需要一个地方来放置较大的下载和正在进行的下载并以非特权方式运行:使用 $XDG_DOWNLOAD_DIR。
- 您需要一个地方来放置缓存文件,该文件应该是持久的并且以非特权方式运行:使用 $XDG_CACHE_HOME。
- 上述内容均不适用,您需要放置一个不需要持久性的小文件:使用 $TMPDIR 并在 /tmp 上进行回退。并使用 mkstemp() 和 mkdtemp() ,而不使用任何自制的东西。
- 否则使用 $TMPDIR 并在 /var/tmp 上进行回退。还可以使用 mkstemp()/mkdtemp()。
请注意,上述规则仅是我们建议的。这些规则考虑了我们对这个主题的所有了解,并避免了我们所看到的当前和未来发行版的问题。请考虑更新您的项目以遵循这些规则,并在编写新代码时牢记它们。
我们要强调的一件事是 /tmp 和 /var/tmp 实际上通常不是您用例的正确选择。这些目录有有效的用途,但通常另一个目录实际上可能是更好的地方。因此,请小心,考虑其他选项,但如果您确实选择 /tmp 或 /var/tmp,那么至少确保使用 mkstemp()/mkdtemp()。
我看错了/tmp
如上所述,我们有点摆脱了 X window 系统使用的遗留套接字。tmpfiles.d/x11.conf
。看起来更像是依赖合作:)。我假设代码已经过审核,因此拒绝服务是可能发生的最糟糕的情况。
答案4
根据文件系统层次结构标准,
/run
用于运行时变量数据,即自重新引导以来有关正在运行的系统的信息/tmp
是临时文件的通用位置。
因此,有关守护进程状态、登录用户、安装的可移动设备等的任何内容都将进入,/run
而程序创建的临时文件将进入/tmp
.
编辑:正如@JdeBP 在下面的评论中指出的,
FHS 允许进行常规的 cron 作业设置,定期清除
/tmp
“旧”文件;没有这样的机制旨在用于/run
.因此,程序对所放入的任何东西的生命周期的期望有严格的限制/tmp
。虽然程序可以期望文件在持续运行的系统中存活更长时间/run
,但它们也应该在那里进行更多的自我整理。