/tmp 和 /run 有什么区别?

Dir*_*ann 46 linux filesystems fhs files

根据FHS-3.0/tmp用于临时文件和/run运行时变量数据。数据输入/run必须在下次启动时删除,这不是/tmp,但程序仍然不能假设数据输入/tmp将在下一次程序启动时可用。这一切对我来说似乎很相似。

那么,两者有什么区别呢?程序应该根据哪个标准来决定是将临时数据放入/tmp还是放入/run

根据 FHS:

程序可能有一个子目录/run;对于使用多个运行时文件的程序,鼓励这样做。

这表明“系统程序”和“普通程序”之间的区别不是标准,程序的生命周期也不是标准(例如,长时间运行与短期运行的进程)。

尽管 FHS 中没有给出以下基本原理,/run但引入它/var是为了克服安装太晚的问题,因此需要/var/run使用肮脏的技巧才能足够早地提供。然而,现在随着/run被引入,并且考虑到它在 FHS 中的描述,似乎没有明确的理由同时拥有/run/tmp

cou*_*ode 23

目录/tmp/usr/tmp(后来的/var/tmp)曾经是所有东西和每个人的垃圾场。对这些目录中文件的唯一保护机制是粘性位,它限制删除或重命名文件的所有者。正如 marcelm 在评论中指出的那样,原则上没有什么可以阻止某人使用服务使用的名称(例如nginx.pidsshd.pid)创建文件。(实际上,启动脚本可以先删除此类伪造文件。)

/run是为长期服务的非持久运行时数据而建立的,例如锁、套接字、pid 文件等。由于它对公众不可写,因此它可以保护服务运行时数据免受混乱/tmp和清理那里的作业的影响。确实:我运行的两个发行版(没有双关语)在 上的权限为 755 /run,而/tmp/var/tmp/dev/shm就此而言)权限为 1777。

  • _它只是将服务运行时数据与 `/tmp` 中的混乱分开 - 还为来自各种清理工作的所述数据提供了一个安全港,这些数据在整个 `/tmp` 中被践踏。 (3认同)
  • _"/run 在技术上不是必需的,它只是将服务运行时数据与 /tmp 中的混乱分开。"_ - 也是一件好事,因此非特权进程不能占用系统服务想要使用的名称。如果 nginx 想要使用 `/tmp/nginx.pid`,但它已经存在,因为一些行为不端的程序,这有点糟糕。`/run/` 通过要求写入权限来防止这种情况。 (2认同)

R..*_*ICE 18

/tmp是用于创建临时文件和目录的位置。它不能用于存储“众所周知的名称”(即另一个进程可以知道的名称,而不必以某种方式将名称传递给它),因为没有人拥有名称空间的所有权;任何人都可以在那里创建文件。因此,当您有一个需要文件(即不是管道等)作为输入或输出的实用程序时,您通常会使用它,只要您传入该名称,任何(随机生成的)名称都将起作用。

从历史上看,有些东西(如 X)违反了这一原则,并将众所周知的名称(如.X11-unix)放在/tmp. 这当然是有问题的,并且允许任何用户通过首先竞相创建所需名称的文件来 DoS 需要这样做的服务。这些东西属于/run(或等效地,/var/run如果您不订阅 Freedesktop.org 修正主义)。当然更好的是修复它们,不要在全局命名空间中使用众所周知的名称,而是传递路径名。

  • `/run/` 本身是被 FHS 采用的,我看不出它和 fd.o 有什么关系。除非我们真正想抱怨的是对两者都有贡献的未指明的开发工作。 (2认同)

sou*_*edi 17

没有理由同时拥有 /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 套接字运行守护进程的一个版本。

来自 Lennart Poettering 的原始信息

请注意,下面 Poettering 的清单声称这/tmp对“小文件”有用,而/run应该只用于“通信原语”。我也不认为这种区别是正确的。的海报男孩/runudev,我很确定/run/udev包括内部数据库。一旦你有了一个/run目录,我认为没有人想要遵循声称的区别并创建另一个目录来混乱/tmp. 所以在实践中我们只是使用/run现在。

使用世界可写的共享命名空间 [如 /tmp] 用于通信目的一直存在问题,因为要建立通信,您需要稳定的名称,但稳定的名称为 DoS 攻击打开了大门。这可以通过在早期启动期间为某些服务建立受保护的 per-app 目录来部分纠正(就像我们为 X11 所做的那样),但这只能部分解决问题,因为这只有在每个软件包安装后都重新启动时才能正常工作。

...

Fedora 的另一个功能(针对 Fedora 17)通过隔离各种服务的 /tmp 命名空间,更改了许多系统服务的 /tmp 语义,使它们更安全

...

因为 /tmp 不再一定是共享命名空间,所以它通常不适合作为通信原语的位置。

...

[/run] 保证是 tmpfs,因此在启动时自动刷新。除此之外,不会进行自动清理。

...

以下是我们建议您(Linux 应用程序开发人员)如何选择要使用的正确目录的粗略指南:

  1. 您需要一个地方来放置您的套接字(或其他通信原语)并且您的代码以特权方式运行:使用 /run 下的子目录。(或在 /var/run 下以获得额外的兼容性。)
  2. 您需要一个地方来放置您的套接字(或其他通信原语)并且您的代码以非特权方式运行:使用 $XDG_RUNTIME_DIR 下的子目录。
  3. 您需要一个地方来放置较大的下载和正在进行的下载并以非特权方式运行:使用 $XDG_DOWNLOAD_DIR。
  4. 您需要一个放置缓存文件的地方,这些文件应该是持久的并且非特权运行:使用 $XDG_CACHE_HOME。
  5. 以上都不适用,您需要放置一个不需要持久性的小文件:使用 $TMPDIR 并回退 /tmp。并使用 mkstemp() 和 mkdtemp() 而没有自产的。
  6. 否则使用 $TMPDIR 并在 /var/tmp 上回退。也可以使用 mkstemp()/mkdtemp()。

请注意,以上这些规则只是我们建议的。这些规则考虑了我们对这个主题的所有了解,并尽可能避免当前和未来发行版的问题。请考虑更新您的项目以遵循这些规则,并在您编写新代码时牢记这些规则。

我们要强调的一件事是 /tmp 和 /var/tmp 实际上通常不是您用例的正确选择。这些目录可以有效使用,但通常另一个目录实际上可能是更好的地方。因此,请小心,考虑其他选项,但如果您确实选择 /tmp 或 /var/tmp,那么至少确保使用 mkstemp()/mkdtemp()。

/tmp如上所述,我们可以避免使用 X 窗口系统使用的旧式套接字。 我看错了tmpfiles.d/x11.conf。看起来更像是依赖合作:)。我假设代码已经过审核,因此拒绝服务是可能发生的最糟糕的情况。

  • 这个答案是各种各样的错误。 (8认同)

dr_*_*dr_ 7

根据文件系统层次结构标准,

  • /run 用于运行时变量数据,即关于自重启以来正在运行的系统的信息
  • /tmp 是临时文件的通用位置。

因此,有关守护进程状态、登录用户、已安装的可移动设备等的任何内容都将进入,/run而程序创建的临时文件将进入/tmp.

编辑:正如@JdeBP 在下面的评论中指出的那样,

FHS 允许诸如定期清除/tmp“旧”文件的 cron 作业的常规设置;没有针对/run. 因此,对于放入的任何东西的生命周期,程序可以预期的内容存在严格的限制/tmp。虽然程序可以期望文件在/run持续运行的系统中存活更长时间,但它们也应该在那里整理得更多。

  • 在这个或任何其他答案中没有指出的一件事,但在 FHS 中指出,并且您可能希望通过以下方式改进您的答案:FHS 允许诸如定期清除“/tmp”的 cron 作业的常规设置之类的事情旧”文件;没有针对 `/run` 的此类机制。因此,对于放在`/tmp` 中的任何东西的生命周期,程序可以期望什么是严格的限制。虽然程序可以期望文件在持续运行的系统上的 `/run` 中存活更长时间,但它们也应该在那里整理更多。 (4认同)