深入了解 Debian 13 的 /tmp 新功能,以及如果你不喜欢它该怎么做

Debian 13 “Trixie ”为 /tmp 引入了一个重要的变化。 传统上,它只是另一个文件系统,尽管有一些特殊的权限,允许系统中的每个人都使用它,但却不能删除彼此的文件。
在 Trixie 中,它被从磁盘移到了内存中,特别是一种叫做 tmpfs 的内存类型。 引用 tmpfs man 页的内容
tmpfs 允许创建内容位于虚拟内存中的文件系统。由于此类文件系统上的文件通常位于 RAM 中,因此文件访问速度极快。
它们也非常容易临时删除……这正是你真正想要的。 有一个老故事,讲的是一个用户被分配到运输管理项目工作。 他登录了他本应存储工作的服务器,看到了 /tmp 目录,发现自己可以在那里上传文件,于是高兴地花了几个月时间把所有工作都放在了那里。 唉,服务器重启后…
这无疑是一个都市传说,但它说明了 /tmp 的真实性质。 如果你需要一次性日志文件、PHP 会话文件、分类空间等,这都没问题。 但你不应该在那里存储任何东西。
这在 Linux 世界并不是什么新鲜事。 RedHat 和它的同类用 tmps 代替 /tmp 已经有一段时间了。
比丢失文件更严重的问题是人们使用了太多的 /tmp。 系统需要 /tmp 来完成基本功能,所以如果 /tmp 占用率达到 100%,系统就会崩溃。 你很容易想到 “我要把这个大压缩文件下载并解压到 /tmp,然后在取出我需要的那个文件后再删除它”……但却忘了删除它。 现在,你占用了 /tmp,久而久之,/tmp 就会被垃圾填满。
Debian 13 的 tmpfs 伴随着……挑战。 和解决方案
现在,你占用的不是磁盘,而是内存。 如果你下载了一个 300MB 的 .zip 文件,并将其扩展到 1GB,然后就忘了它,那么你现在就占用了 1GB 的内存。 哎哟
有两个缓解因素。 首先,默认情况下,Debian 最多只能为 /tmp 的 tmpfs 分配 50% 的内存。 你可以改变这一点。 为此,请键入
systemctl edit tmp.mount
您将进入编辑器(由 EDITOR 环境变量控制),并看到一个更新设置的表单。 在最下方,你会看到一个模板,你可以复制并编辑它:
# [Mount]
# What=tmpfs
# Where=/tmp
# Type=tmpfs
# Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=1m
返回到 “此注释以下的编辑将被丢弃 ”一行之前的部分,然后粘贴如下内容:
[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev,size=25%%,nr_inodes=1m
将其更改为 25%,或者如果您想要一个数字,也可以将其更改为 25%:
[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,nosuid,nodev,size=1G,nr_inodes=1m
改为 1GB。
例如,我有一个 4GB 内存的 Debian 13 VPS。 重新安装后,我发现 tmpfs 的最大容量为 2GB:
# findmnt --target /tmp
TARGET SOURCE FSTYPE OPTIONS
/tmp tmpfs tmpfs rw,nosuid,nodev,size=2007704k,nr_inodes=1048576,inode64
请注意,这是最大值。 如果 /tmp 中没有任何内容,/tmp 不会占用任何内存。
执行 systemctl 编辑后,如下所示:

我得到的信息是

在更改之前,/tmp 的内存为 2GB(4GB 内存的一半):

现在,重载 systemd 并重启 tmp.mount 后,我发现 /tmp 被限制为 1GB:

清理
第二个缓解因素是 /tmp 现在会自动清理。 引用发布说明:
新的默认行为是在最后一次使用(以及重启)10 天后自动删除
/tmp中的文件。/var/tmp中的文件会在 30 天后删除(但不会在重启后删除)。
你可以修改这些策略,排除某些文件(为什么?因为它们是临时文件!),甚至将其应用于其他目录。 请查阅详细手册,但我认为对于 99% 的人来说,默认值就足够了。 我可能会想把清理时间设得更长一些,比如 3 天。
低端背景下的思考
一个值得关注的问题是内存非常低的系统。 虽然 1GB 已成为很多人的最小虚拟机,但 512 内存仍在销售。 允许 /tmp 占用 512 MB 中的 256MB(在加载了内核和重要系统进程后,实际上只有 470-480 MB),要比占用 10GB 或 20GB 文件系统中的 256MB 影响大得多。
幸运的是,如果你不喜欢,退出新的 tmpfs 世界也很容易:
systemctl mask tmp.mount
并重新启动。 我在上面的测试箱中就是这么做的:

现在,我可以在这里放 17GB 的垃圾了。 幸运的是,这些垃圾会如上所述被清理掉。
那么,您打算如何处理 Debian 13 基于 tmpfs 的新 /tmp?

服务器上的Swap在某种程度上违背了 ECC 内存的初衷:你的程序状态现在受制于复杂的 IO 路径,而这种路径没有端到端的校验和保护。此外,你还会得到不可预知的性能。
因此,典型的做法是:在服务器上关闭Swap。他们有服务器的故事吗?
这是个非常好的观点,我从未想到过。
编辑:我认为使用 ZFS 来管理 /tmp 可以解决这个问题。在写入校验和文件系统时,你会获得纠错内存。
ZFS /tmp 可能没问题,但在 Linux 上Swap到 ZFS 是很危险的 AIUI;不幸的是有可能出现死锁 https://github.com/openzfs/zfs/issues/7734
啊,谢谢你指出这一点,我还不知道。
那么,也许可以使用另一个具有重校验和的文件系统?Btrfs或具有完整性的dm-crypt,而不是ext4?
Linux 上的 swapfile 必须直接映射,绕过任何文件系统级校验(参见 https://btrfs.readthedocs.io/en/latest/Swapfile.html)。
为什么不是 dm-integrity?
https://wiki.archlinux.org/title/Dm-integrity
> 它默认使用日志来保证写入的原子性,这实际上将写入速度减半。
在我看来,这并不适合Swap。
https://www.kernel.org/doc/html/latest/admin-guide/device-ma… 说、
> 在另一种操作模式中,dm-integrity 使用位图而不是日志。如果位图中的某个位为 1,则相应区域的数据和完整性标记不会同步–如果机器崩溃,未同步的区域将被重新计算。位图模式比日志模式更快,因为我们不必写两次数据,但可靠性也较差,因为如果数据损坏发生在机器崩溃时,可能无法检测到。
我不清楚Swap模式是否可以这样做(只要不休眠,也许可以),也不清楚它是否能充分防止数据损坏。
我现在看到了:Pro ECC SATA 和 M.2 SSDS
SATA 有基本的 CRC,如果路径(通常是电缆)不好,SMART 中的 CRC 传输错误就会增加。
首先,没有Swap意味着不能驱逐匿名页,而必须驱逐命名页。
其次,进程的二进制文件被映射为命名页(因为它们来自 ELF 文件)。
命名页一般不被理解为 “已使用 ”的内存,因为它们可以被驱逐和回收,但如果你有一个运行着 150MB 二进制文件的服务,这 150MB 看似 “空闲 ”的内存对性能绝对是至关重要的。
如果这 150MB 的磁盘缓存耗尽,机器将耗尽所有 I/O 能力从磁盘重新获取 ELF,很可能导致反应迟钝。有了Swap功能,匿名页面就可以被驱逐,从而大大延迟了锁定时间,因此同样的内存压力会导致更少的停滞。
因此,在Linux的OOM管理得到修复之前,你需要swap。
Swap匿名页也会让系统陷入停滞。使用 swap 时,高内存压力会让系统变得非常慢,而关闭 swap 时,高内存压力很可能会调用 OOM 杀手,让系统剧烈修复。
我所暗示的 OOM 杀手的 “错误 ”是,你所描述的情况不会发生。这并不奇怪,因为磁盘缓存中断是向网络提供大文件的正常运行模式。仅在这种情况下使用 OOM 杀手就会产生问题,但如果没有Swap,其他工作负载也会因此而减速。
这不是一个错误,而是一个公认的问题,目前还没有任何好的解决方案。
我们使用 earlyoom 来解决这个问题。在我们的工作负载中,我们不能容忍任何形式的Swap,在这种情况下,系统最好杀死一个进程以挽救其他进程,而不是让系统变慢或锁定。
服务器上的Swap不是这么用的。
ECC 的目的与 “端到端 ”无关。CPU 与 DRAM 之间的典型路径也不是端到端,因为缓存会使用不同的编码。这通常被认为是没有问题的,因为在 CPU 到内存和内存到磁盘的情况下,每个 I/O 段都有这样或那样的错误检测。一般来说,ECC 并不像加密认证那样可以防止任何可能的更改;它在本质上是针对最常见故障模式的概率分析。
如果从磁盘读取数据时出现校验和错误,那么问题就比内存损坏严重得多。你启动的任何程序都可能会损坏。
不过,如果你在服务器上进行Swap(你应该这样做),Swap必须在 RAID 上进行,否则你的服务器会因磁盘错误而崩溃。
服务器上的Swap并不是为了处理内存不足的问题,相反,服务器上有大量几乎从未使用过的数据,因此应将其Swap出去,为缓存腾出更多空间。
文章忘记提及的第三个缓解功能是,tmpfs 可以被分页到Swap分区。如果你把一个大文件丢在那里却忘了它,如果应用程序需要更多内存,那么所有文件最终都会进入交换分区。
什么交换分区?
我是开玩笑的。我想有一些 Linux 系统从未配置过交换分区或交换文件。
我同意你的说法。我不Swap。进程死亡。OOM。Linux 可以恢复,不会丢失数据。只是暂时无法使用。
Linux的OOM杀手有点靠不住。它喜欢长时间冻结你的系统,因为它在想办法解决问题。然后它就开始杀死随机的 PID,试图像系统轮盘赌一样夺回内存。
当你没有Swap空间时,这种情况尤为糟糕。我发现添加一个约 500 MB 的小Swap文件能让系统运行得更好,即使系统内存只有半 TB,这也有助于减少冻结问题。
我总是禁用超量提交(尽管 Linux 无法提供完全准确的严格内存统计),而且我宁愿不使用交换文件,但 Linux 虚拟机维护者一直表示,他们在设计和调整虚拟机子系统时考虑到了交换文件。抽象地说,Swap是必要的吗?Linux上需要Swap吗?但如果在没有Swap功能的情况下,Linux 做不到你所期望的那样,也不要感到惊讶,更不要指望 Linux 会在没有Swap功能的情况下为提高性能付出多少努力。
我从未在我的个人服务器上遇到过麻烦,但我曾在一些地方工作过,尤其是在运行对虚拟机子系统(如 JVM 和大型 Java 应用程序)造成负担的应用程序时。如果有人想知道,即使应用程序分配的匿名内存总量从未超过系统 RAM,为什么Swap仍然有用,原因之一就是与缓冲缓存的交互以及在压力下的驱逐。
> 但是 Linux 虚拟机维护者一直表示,他们在设计和调整虚拟机子系统时考虑到了Swap。
有没有可以向怀疑论者展示的引文?
安装 earlyoom 或其近似版本。这基本上解决了系统长时间冻结的问题。
我还没见过 OOM 杀手无用的杀毒方式–通常它要么会杀死失控的罪魁祸首,要么会释放出足够的空间来帮忙。
至于你说的 “即使是半 TB 内存的系统”,按理说,系统越大,这种行为就越严重,因为一旦出现问题,需要处理的东西就会更多,而这需要更长的时间。我的工作服务器有 1.5TB 内存,在我安装 earlyoom 之前发生的 OOM 事件一点也不美妙。
> 对于你说的 “即使是半 TB 内存的系统”,合乎逻辑的是,系统越大,这种行为就越糟糕,因为当事情发生偏差时,有更多的事情需要解决,而这需要更长的时间。我的工作服务器有 1.5TB 内存,在安装 earlyoom 之前发生的 OOM 事件一点也不美妙。
我的意思是,即使内存很大,也不必超过几百 MB。区别不在于交换文件的大小,而在于它的存在,而让它与内存成正比的建议在很大程度上已经过时了。
> 我还没亲眼见过OOM杀手无益地杀人呢
啊,经典的 Linux 爱好者格言:“从未发生在我身上意味着从未发生在任何人身上”。
我最喜欢看到 OOM 的情况是
在只安装了 mysql 的机器上杀死 mysql,而这台机器是生产用的;
以及最棒的一点–杀死 sshd。当然,我只能通过 BMC/IPMI 控制台或虚拟机的 KVM 控制台在 tty0 上看到这些情况后才能报告。
nohang 也一直是桌面的好帮手,在内存压力和合理的默认设置下提供友好的通知。
除了这些辅助工具,与 OOM 相关的大量 systemd 陷阱(OOM 调整分数默认值和限制、默认情况下杀死 tmux 用户会话等等等等)多年来确实让我伤透了脑筋。而内核在这方面的进展也一直不尽如人意。
还有,为什么火狐浏览器只在 Linux 下关闭了内存不足时自动卸载标签的功能?自从我打开 browser.tabs.unloadOnLowMemory 后,用户体验好了很多……
这只是轶事,但我曾多次遇到 Linux OOM 杀手破坏 Kubernetes 节点上的 OVS(开放虚拟交换机)。
这让我真的不介意设置一点交换空间以防万一。
据我所知,OOMKiller 会随机选择一个页面,找出该页面的所有者,然后杀死该进程,如此反复,直到有足够的内存为止。这会偏向于内存分配较大的进程,但也可能杀死任何进程。
> 如果 OOM 杀手有必要杀死进程,那么将根据所谓的 OOM 分数来决定杀死哪些进程。每个进程都有一个与之相关的 OOM 分数。
> Linux 中的每个运行进程都有一个 OOM 分数。操作系统会根据几个标准来计算一个进程的 OOM 得分,这些标准主要受进程正在使用的内存量的影响。通常,OOM 分数在 -1000 到 1000 之间。当 OOM 杀手需要杀死一个进程时,同样由于系统内存不足,OOM 得分最高的进程将首先被杀死!
https://learn.redhat.com/t5/Platform-Linux/Out-of-Memory-Kil…
无论如何,Swap仍然会发生。如果没有交换空间,内核就会交换代码页。因此,运行程序。当相应进程下一次调度并需要这些代码页时,就需要再次从磁盘加载这些代码页。
这样做的效率并不高,这也是为什么通常建议使用一些实际交换空间的原因。
与Swap不同的是,释放代码页不会写入 HDD/SSD,而只需要在将来再次需要时重新加载代码页,因此比Swap更有效率。
20 多年前,我就不再在我所有的 Linux 服务器、台式机和笔记本电脑上使用Swap功能了。当时,它是一个很大的改进,从那时起,它从未引起过任何问题。不过,我对内存的安装量一直很慷慨,对于任何至少有 NUC 大小的电脑,多年来我从未使用过低于 32 GB 的内存,而对于新电脑,我不打算使用低于 64 GB 的内存。
有了足够新的 Linux 内核,使用 tmpfs 作为 /tmp 完全没问题。尽管如此,几十年来,使用 tmpfs 代替 /tmp 一直很危险,因为通过 /tmp 复制文件会丢失元数据,比如截断文件时间戳和删除扩展文件属性。
多用户计算机用户之间经常通过 /tmp 复制文件,因为在这些计算机上没有其他所有用户都有写入权限的目录,Linux tmpfs 以前的行为让他们非常惊讶。
在增加交换容量之前,在 SteamDeck 上使用桌面模式非常有趣。启动一个游戏,一切都冻结了,出去散步一个小时,看到游戏终于结束了,然后泡杯咖啡喝,系统就又可以使用了。
Fedora 早在 debian 之前就这么干了。我还记得我在 /tmp 上对 .iso 文件进行 wget 操作,结果整个 wayland 会话都被 OOM 杀手杀死了。
我仍然觉得这是个糟糕的主意。
如果你想要一个磁盘支持的 tmp,请使用 `/var/tmp` 。
我以为 /var/tmp 是给应用程序用的,而 /tmp 是给用户用的。
> /tmp/
> 存放小型临时文件的地方。该目录通常被挂载为 tmpfs 实例,因此不应用于较大的文件。(使用 /var/tmp/ 来存放较大的文件。)该目录通常在启动时被刷新。此外,在一定时间内未被访问的文件可能会被自动删除。
资料来源 https://uapi-group.org/specifications/specs/linux_file_syste…
但这是在修改之后写的 😀
小知识:《CIS 指南》(应用于服务器的安全任务,以通过增强型安全审计,从而符合标准的一种说法)中有一项要求 /var/tmp 必须绑定挂载到 /tmp(以及在 /tmp 上设置特定的安全选项)。试图通过 CIS 审计的服务器(在我与企业的工作经历中非常常见)很可能没有唯一的 /var/tmp。
> 我以为 /var/tmp 是给应用程序使用的,而 /tmp 是给用户使用的。
/tmp 是用于 “绝对 ”临时的东西,因为在许多/大多数系统中,它在重启之间就会被删除。/var/tmp是 “相对 ”临时的,因为应用程序可以把正在处理的内容放在这里,但如果系统崩溃,这些内容不会被删除,而且可以在重启后恢复。
这就是现在拥有一个大交换文件的好理由。
但要注意的是,如果你现在没有swap文件,而启用了它,就会带来崩溃的风险。
如果你已经有了交换文件,那就无所谓了,但我已经遇到了足够多的故障,所以我现在几乎在所有的服务器上都禁用了交换文件。
这种情况很少见,但一旦发生,服务器通常会完全没有反应,因此你必须硬重置它。我更希望试图使用过多内存的应用程序被 oom 管理器杀死,然后我就可以通过 ssh 登录来解决这个问题了。
[1] https://docs.redhat.com/en/documentation/red_hat_enterprise_…
不是这样的。没有Swap,你就已经有了崩溃的风险。这是因为 Linux 将进程正在运行的所有代码段都视为干净的、可从缓存中驱逐的代码段,因此基本上等同于 swap,即使在没有 swap 的情况下也是如此。在内存不足的情况下,Linux 会很乐意驱逐所有干净的页面,包括下一个要调度的进程需要执行的页面,这就会导致系统崩溃。在低内存条件下,由于没有交换,服务器仍然会因为刷新而反应迟钝。
将交换性设置为零并不能解决这个问题。禁用Swap也不能解决这个问题。禁用 overcommit 可以解决这个问题,但如果你正在运行的某些进程分配的内存远大于其使用的内存,这可能会带来无法接受的弊端。安装 earlyoom 来防止出现真正的低内存情况,确实可以解决这个问题,而且可能是最好的解决方案。
在服务器上禁用交换功能已成为严格部署的事实标准。
Swap的故事需要认真升级。我认为内存中的/tmp是个好主意,但我也认为特定的/tmp需要一个Swap支持(最好有压缩功能,ZSWAP),而不是主系统。
> Disabling swap on servers is de-facto standard for serious deployments.(在服务器上禁用Swap功能是严肃部署的事实标准)。
我想在过去的几十年里,我并没有认真地进行过部署,因为我部署的(硬件)系统都有一些Swap功能,即使只是一个文件。
你的Swap率是多少?
Swap似乎总是更适合台式机使用。在服务器上,你需要为应用程序栈提供真正的内存。
几乎所有关于交换分区的指南都参考了十多年前的旧分配器行为–即使你有足够的内存,没有交换分区也确实会遇到奇怪的问题。
简短(不准确)的总结是,即使还不需要,它也会尝试使用一些 swap 分区,这在内存足够但成本过高的情况下是合理的,但当我们开始在大多数情况下拥有足够的内存时,分配器就变得更加复杂了。
如今,除非你开发的产品有某些限制,否则通常不需要Swap,在这种情况下,无论如何你都会手动调整低内存性能。只要不购买低于 32GB 的产品,就不会有问题。
一般建议中有大量的脚枪,默认配置下的本地内存存储服务等
因此,理想的行为应该是
ChatGPT 认为这是无法实现的,不过它认为 cgroup2 可以实现类似的功能。
这就是为什么我使用超commit 2 和每个服务器的不同比例。
……虽然我不知道为什么我们要在 2025 年考虑这个问题。
我猜你会密切监控服务的 OOM,然后根据需求进行调整?
是的,差不多是这样,在应用程序允许的情况下,也会在所有地方配置内存限制。有些软件还能比较优雅地处理 malloc 故障,这对我们帮助很大(感谢 Postgres 开发人员)。
我花了一天的时间考虑这个问题,我真的看不出有什么大的负面影响,唯一的问题就是 OOM 条件的通知,而这只需要系统日志的 regex 匹配。好计划。
从以前的 Debian 版本升级时,所提到的定期清理 tmp 文件功能并不是开箱即用的,请参见 https://www.debian.org/releases/trixie/release-notes/issues…. 。
事实上,了解这一点非常方便和实用,特别是在 “低端机 ”的背景下,我个人更希望我的应用程序有内存,并且完全可以接受 `/tmp` 任务有点慢(让我们实事求是地说,反正整个机子都 ‘慢’,这里的慢是 “SSD 上的虚拟机块设备 ”而不是 1990s 旋转的铁锈的因素)。
我惊奇地发现,tmpfs 用于 /tmp 的情况早已有之,这种变化很好。
但在我看来,自动清理功能非常糟糕。无论是台式机还是服务器,运行时间超过一年的机器,我从未见过 tmp 被遗忘的垃圾填满的情况。只有在解压过大的文件或类似文件时才会出现这种情况。但它就在现场。
以前,你可以在这里存储缓存或其他类似的东西,直到下次重启。让文件在随机时间后自动删除,这看起来太武断了,也是意外错误的根源。
我不知道这个功能从何而来,但当这样愚蠢而危险的事情发生时,我敢打赌,这又是 systemd “我最了解什么对你有好处 ”的破功能塞进了我们的喉咙……
如果它来自 systemd,预计有一天它会不小心删除你的重要文件,比如你的 home 目录或 nvme EFI 分区的符号链接……
> 我从没见过 tmp 被遗忘的垃圾填满的情况。
这可能与我合作过的开发人员类型有关,但这种情况经常发生。监控系统发出抱怨,然后你进入检查,结果就会看到几千兆字节的垃圾,这些垃圾是由低劣的软件或无法自行清理的脚本倾倒在那里的。
问题是,如果你是操作人员,而不是开发人员,你并不总是知道什么是可以安全删除的。定期自动清理 /tmp 会破坏一些东西,而要求运维团队禁用自动清理功能要比在开发人员的下一次冲刺中解决这个问题容易得多。
自动清理:从文件中获取最后访问时间,然后只自动清理过去 n 小时(如 24 小时)内未被访问的文件?应该比较安全。
开发人员把所有东西都扔进了 tmp,所以它也积累了大量隐私数据
我在我的日常驾驶设置中尝试了各种不同的方法。这里的设计选择可能有三个方面:
将 tmpfs 存储在内存中:易失但仅限于空闲内存或交换空间,并写入磁盘
将 tmpfs 存储在专用卷上: 既然我们无论如何都要写入磁盘,那就把它变成一个提交到磁盘的轻量级特殊用途文件系统
将 tmpfs 存放在磁盘上,但定期清理:清理的其他设置–多久清理一次、哪些内容应该保留、将文件寿命与机器重启挂钩?这些问题的答案在不同应用程序之间的差异比在不同文件系统之间的差异更大,因此由用户空间来清理更为灵活。
最后,我最担心的是丢失我不想丢失的文件,无论是重启清理还是定时清理等等。我选择了根据需要手动清理临时文件。
根据定义,tmpfs 本身基本上就是一个 ramdisk。我猜你说的 tmpfs 是指 /tmp?
是的,我最近不太小心。
如果你设置了Swap,那么过期文件就会被写回磁盘,这样至少不会因为文件存储在 tmpfs 上而无限期地 RAM。
但这仍然不是一个理想的解决方案。
我同意自动清理的说法,在把 /tmp 用作 Yocto build 的内存盘几天后,我就发现了这个问题。丢失了一些补丁,但并不严重。
如果我对磁盘速度感到满意,为什么还要使用系统内存?有哪些具体的使用情况需要这样做?
像树莓派(Raspberry Pi)这样的电脑,其操作系统位于 SD 卡上,将从中受益匪浅。
是的。关于如何减少循环次数、延长 SD 卡使用寿命,有很多建议。这篇文章有很多建议,tmpfs 绝对是其中之一。https://raspberrypi.stackexchange.com/a/186/32611
从技术上讲,它会对磁盘的写入次数产生一些影响,并略微降低磨损程度。
大多数磁盘都有大量可用的写入周期,因此无论如何都不会有问题,但这只是微不足道的好处。
我已经有 15 年没用过非 tmpfs(基于磁盘)的 /tmp 了。
在 NetBSD 上不需要它,内存可以归零,系统也不会崩溃。当我转用 Linux 时,OOM 问题一开始让我很震惊,但我学会了如何避免它。
我使用的是小型计算机,用户态安装在内存中并从内存中运行,没有Swap;我只对非临时数据使用长期存储。
https://www.kingston.com/unitedkingdom/en/blog/pc-performanc…
我仍然喜欢使用多实例化的 /tmp 和 PrivateTmp(systemd)。这可能会让不了解命名空间的管理员感到困惑或厌烦,但我知道这无疑关闭了坏人滥用 /tmp 的攻击载体。
https://www.redhat.com/en/blog/polyinstantiating-tmp-and-var…
如果系统内存压力过大,文件 tmpfs 就会Swap出去。
如果出现这种情况,读回文件的速度会比一开始就把文件存储在磁盘上慢得多。
对大多数用户来说,这一改变不仅不会加快速度,反而会减慢速度。你不是在缓存重要文件,而是在无用的临时文件上浪费内存。然后,系统会将其Swap出去,这样你就能重新获得缓存,而重新读取的速度却非常慢。
这一改变是个错误。
为什么从交换文件读回数据的速度会比将数据保存到磁盘再读回的速度慢–更不用说 “从内存上 ”慢了?
因为每次换回的数据只有 4kb
这也是因为文件系统更有可能将文件的连续部分连续存储在磁盘上,而Swap则会随机地将 4kB 块分散到各处,因此你需要处理的是随机存取读取速度,而不是吞吐量读取速度。
在旋转的磁盘上使用 FAT 时,这种说法成立,但在 SSD 上使用 ext4 时,这种说法就不成立了。ext4 是基于范围的,因此不会出现碎片开销。
交换分区没有文件系统,它是一个线性块列表。
我和父母都没这么说。混淆了?
ext4 与文件由 swap 支持时发生的情况无关;即使有 swapfile,mm 子系统也会或多或少地从文件系统的背后访问与 swapfile 对应的磁盘。
提出(读取大小/4kb)请求的开销(可能导致每一页的读取过程停滞)即使在 ssd 上也是相关的;除了移动磁头和等待盘片旋转到位外,随机存取还有其他成本,而这些成本在固态存储中仍是相关的。
你的评论写得像在反驳上面的人,但文字支持他们的说法: 在这方面,文件系统比Swap更快。
你的意图是什么?
为什么?
因为页面大小。它和其他页面一样。
这其实说不通。如果 /tmp 是磁盘上的目录,那么导致交换的内存压力也会从页面缓存中驱逐文件,同样会导致缓存缺失,读取速度也会大大降低。
从文件系统读回文件比从 swap 读回文件要快得多。
现在大多数系统可能都不会遇到内存不足的问题,不是吗?这将减少对固态硬盘的磨损。
此外,你还可以轻松禁用它: https://www.debian.org/releases/trixie/release-notes/issues….
如果你在虚拟机中运行,你可能没有那么豪华的内存。
当我的 Linux 虚拟机开始Swap时,我必须等待一个小时或更长时间才能恢复控制,或者直接重启虚拟机。
没错,但如果是虚拟机,它可能是由类似 ansible/terraform 的东西配置的?如果是这样,很容易添加一个初始脚本来禁用此功能,再也不用担心了。
你运行的是哪个发行版? systemd-oomd 杀死进程的速度比之前的要快一些(几分钟后系统就会变得缓慢、卡顿)。对于你希望尽快恢复在线的服务器来说,还是太慢了。
至少现在当内存耗尽时,它会杀死消耗内存最多的进程。几年前,它会杀死我的桌面会话!
没错,传统上这是因为 X 服务器通常占用大量内存,因此对于 OOM 杀手来说非常有吸引力。但在过去 15 年左右的时间里,我们采用了一些启发式方法,故意阻止 oom 杀手杀死 “重要的东西”。
我在自己管理的系统上安装了 earlyoom。它能在系统仍有反应时杀死一些东西,而不是在系统处于需要数小时才能恢复的状态时杀死一些东西,从而防止低内存的混乱。
这不是内存不足的问题,而是要把内存留给更重要的东西:缓存。
这种更改会将最不重要的数据(临时文件)放在内存中,同时驱逐更重要的缓存数据。
在 512 MB 或 1 GB 的小型 VPS 系统上,你更有可能注意到(如果 /tmp 实际上被系统上运行的内容使用)。
为什么 Linux 中没有通过 unionfs 写入的功能?感觉这是一个非常有用的工具。没有人需要它吗?我真想写一个 NFS 接口的。
编辑:谢谢你,jaunty。但所有这些都是设备级的。即使 bcachefs 也是块设备级的。它不允许联合 FUSE FS 等。不在文件系统级实现这一点似乎很奇怪。
Dm-cache!https://www.kernel.org/doc/Documentation/device-mapper/cache…
你的意思是说,你可以标记仍然使用底层文件系统的文件?在我的记忆中,大约 20 年前曾有过这样的实验,但后来认为增加的复杂性不值得。取代这一切的实现一直非常稳定(与之前的实现不同),我也在大量使用它,所以我认为他们说得有道理。在此基础上,还可以编写一些写透行为的脚本。
编辑:维基百科将 overlayfs 和 aufs 列为活跃项目,而 unionfs 早于这两个项目。也许是 unionfs v2 取代了这一切?也许是我的幻觉…
Overlayfs 不支持穿透写入,我相信 unionfs 和 aufs 也不再支持穿透写入。
我想要的和写入式缓存的工作原理差不多。
1. 写入顶级 FS?写入向下级联,但读取速度很快
2. 顶层 FS 中没有数据?读取到底层,然后再读取到顶层,这样以后的读取就会很快。
我觉得这是在混合议程。是为了更有规律地释放 /temp(这样你就不会无意中依赖它,节省空间等),还是为了提高性能?我觉得对于现代的 nvme(或只是 ssd)来说,开箱即用 tmpfs 的论点很难成立,如果你在特殊情况下(例如你确实需要 ram 速度或在 SD 或 eMMC 上运行),那么你就会知道自己应该使用 tmpfs。
(另外,很抱歉,本文绝对不构成对任何问题的 “深入探讨”)。
使用文章中的例子,提取归档文件。当然,这种用例不可能在实体中使用内存?如果你要处理的是一个不小的 100GB 归档文件,会发生什么情况?
谁会带着 100GB 以上的Swap机到处跑?
如果你想要磁盘支持的 tmp,请使用 `/var/tmp` 。不知道为什么这篇文章省略了这一点。
所以你现在必须做出决定,这个文件是小还是大?这就把问题推给了用户和程序。(这也是一个非常现实的问题,我们对 libguestfs 进行了大量修改,以区分 “小 ”文件和 “大 ”文件,并将它们放到 /tmp 或 /var/tmp 中。在某些系统中,如果 /tmp 不是 tmpfs,则完全没有必要)。
如果你想通过安全审计,/var/tmp 是不允许的,它 MUST 必须是绑定挂载到 /tmp
要求绑定挂载(或允许的其他选项)的理由是什么?
谁会带着 100GB 以上的 /tmp 分区到处跑?
我们的默认服务器镜像自带 4.4GB /tmp 分区…
我运行一个脚本,每天轮换我的 /tmp/,因此我可以访问 /tmp/20250828/ 中昨天的 tmp 文件,以此类推。
我的 /tmp 是用于下载和临时工作的默认文件夹。它很容易就会增长到 100GB 以上。
当然,但请注意,你的用例特别违反了 fhs 和 posix 规范:
>程序不得假定 /tmp 中的任何文件或目录在程序调用之间被保留。
>尽管存储在 /tmp 中的数据可能会以特定站点的方式被删除,但建议在系统启动时删除位于 /tmp 中的文件和目录。
https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s18.htm…
显然,您可以按照自己的喜好使用您的文件系统,但我认为 Debian 不应该考虑一般建议/规范之外的用途。
程序不应该假定 /tmp,用户建议这样做就可以了。
用户并没有 “建议 ”这样做,也没有询问这样做是否合适。他们只是这么做了。他们想在自己的电脑上做什么都是允许的。
你回复的那个人是说,tmp 用于临时存储,可能会在重启之间消失。tmp 目录过去状态的永久存档不是临时的。
我指的是从程序的角度来看。你不能假定 /tmp 是稳定的,但当用户告诉你它很好时,它就是好的。
> tmp 目录过去状态的永久存档不是临时的。
从程序的角度来看,它仍然是不稳定的,因为文件并没有留在它们原来的位置上。
很长一段时间,我的默认下载文件夹都是 /dev/shm。重启后,所有文件都会消失。现在我可以直接使用 /tmp
我甚至在我的 Windows PC 上使用过类似的东西,有一个 1GB 大小的 B:/ 磁盘是我的下载文件夹。自动清理变得简单了。
这让我想起了空格键加热 xkcd: https://xkcd.com/1172/
(不是取笑工作流程什么的,只是像 tmpfs 这样破坏东西的改动非常正确)
即使是你的用例,也会从任何改变中受益,因为你只需移动到 /tmp2 而不是 /tmp,它实际上会按照你的意愿运行。
因此,99.9% 的用户和你都会从更改中受益。我相信还有一些人真正依赖于非常规的使用方式,但他们目前还保持沉默。
你的用例听起来更像是 “scratch ”文件夹,而不是 /tmp 的真正用途。
在这里,更容易让人上当受骗而又容易被忽视的是,/var/tmp 中的文件可以在重启后继续保存,但在 30 天后仍会被自动删除。
我读了这篇文章,真的不明白。如果有未使用的文件,Linux 已经将其缓冲到 RAM 中了,为什么还要这样做?
“这样你就不需要从磁盘读取文件了 ”这种说法纯属扯淡,因为 tmpfs 数据可以被驱逐到 swap 中。如果内存压力很大,你仍然需要从磁盘读取数据。
内存压力大也是导致磁盘支持的 /tmp 运行缓慢的原因。完全没有改善。
systemctl mask tmp.mount"–在这种情况下运行的最重要命令。
将 /tmp 放入内存实在不是个好主意。文件系统已经在必要时使用内存,并在内存有压力时向文件系统溢出。如果它们没有正确做到这一点(它们确实做到了),那就修复你的文件系统!这对一切都有好处。
你会这么想,但在 ext4 中,对新文件的首次写入会撞击磁盘(代码中提到这是一种变通方法)。Btrfs 的做法是正确的。
听起来修复 ext4 的问题能让很多事情变得更快。
这正是 /dev/shm 的用途… 而且可以明确使用,没有任何麻烦。如果有人真的想让 tmp 位于内存中(以减少 SSD 的耐久写入或名义上加快速度),他们可以编辑挂载。
这感觉像是一个非常不必要的改动,而且文章中也没有提出令人信服的相反论据。
作为一个需要使用所有内存的人来说,这很烦人,但至少可以关闭。
我以为 /dev/shm 是 ramdisk?
/dev/shm 会保留吗?当然会,但它的内存上限也是 50%。这是否意味着 /dev/shm + /tmp 现在可以达到 100% 内存?还是它们共享相同的内存预算?
预算相同
为什么会有这样的变化?写入速度会比磁盘快,但我不知道如果内存是珍贵的商品,我宁愿它只是我写入磁盘的一部分。
这是一个来自 systemd 人员的愚蠢想法。他们从未正确解释过为什么这是个好主意,但这是 systemd 的默认设置,出于某种原因,发行版都会遵从这个默认设置。
tmpfs比systemd早了十年。
它之所以成为 Fedora 和其他沿用 systemd 的 Linux 发行版的默认设置,是因为它是 systemd 的默认设置。
在 Solaris 上,这也是个馊主意,但至少在那个年代,内存和磁盘存储之间的权衡与现在的 NVME 驱动器等大不相同。
不是吧,tmpfs 的引入和使用远早于 systemd。
没有人质疑这一点。他抱怨的是 systemd 将 /tmp 切换成了 tmpfs,而不是 systemd 的人制造或造成了 tmpfs。
我很清楚。我在 Solaris 上用过它。
Solaris/SunOS。那真是一段美好时光。干杯,伙计!
在 RHEL 中,我们曾这样载歌载舞。没关系。如果你需要持久的 tmp 存储空间,使用 /var/tmp 即可。Gnome 和 X 以及 tmux 不会让你Swap,如果要Swap,请运行 xfce。