返回资讯中心
外部精选
软件工程
#开发者实时流

用户抱怨 NixOS 的 nix-shell 将 TMPDIR 指向内存目录导致空间不足

来源标题:Maybe NixOS just isn't for me (2024)

一名用户在使用 NixOS 时遇到临时目录空间耗尽问题,根源是 nix-shell 将 TMPDIR 设为内存支持的 /run/user/$UID 而非磁盘上的 /tmp。该用户将 /run 目录扩至 8GB 后问题仅被推迟,最终在 Reddit 和 GitHub 上找到其他用户对同一行为的抱怨。

Hacker News 最新sammatilda2026/11/14 · 今天23 分钟阅读

以下正文由 AI 翻译自 Hacker News 最新(原文版权归原站所有),可能存在偏差,重要内容请以原文为准。

我很快找到了这篇文章,它似乎和我的问题密切相关。看起来 /run/user/$UID 这个目录被分配了固定大小的空间,作为一种 tmpfs,而正是这个目录空间耗尽了。按照文章的建议,我检查了 configuration.nix,把 /run 目录的大小增加到了 8 GB。

我重建了系统,又试了一遍,但很快再次遇到了同样的问题。增大运行时目录的容量似乎只是推迟了问题出现的时间,所以这并不算真正的修复。

后来我找到了这个 reddit 帖子和这个 github issue,很有帮助,但老实说也让我相当困惑。

如果你通读那个 issue,会发现几乎所有人都在抱怨:nix-shell 在 $TMPDIR 尚未设置时,会把它设为 $XDG_RUNTIME_DIR(通常是 /run/user/$UID),而不是 /tmp。

nix-shell 到底为什么要设置 TMPDIR?@YPares、@davidar 和我遇到的一个问题是,/tmp/ 是磁盘支持的,而 $XDG_RUNTIME_DIR(即 /run/user/$UID)这个默认的 TMPDIR 是内存支持的,所以有时编译器创建的临时文件足够大,用户就会内存耗尽。

只是想分享一下我的经历。我所在的公司会在 shellHook 里做不少事情,这个 hook(在 CI 上)失败了,因为我之前不知道 TMPDIR 是内存支持的。用 TMPDIR="$(mktemp -d)" nix-shell 运行就解决了。也许应该在手册的某个地方提一下?

今天也遇到了这个问题。nix-shell 和 nix-build 不应该把 TMPDIR 设成 /run。任何指望能在 mktemp -d 里创建大文件的进程,如果跑在 nix-build 或 nix-shell 里,就要遭殃了。

我也刚被这个问题坑了。/tmp 本来就是放临时文件的,为什么不用它呢?

在大多数现代系统上,/tmp 也是 tmpfs,所以用 /tmp 还是 /run 其实无所谓。

我觉得让人困惑的地方在于:当 TMPDIR 没设置时,它会回退到 XDG_RUNTIME_DIR。我有好几个同事都踩了这个坑,尤其是在 Ubuntu 上,那里给 XDG_RUNTIME_DIR 分配的空间非常小(远小于可用内存)。

有用户争辩说这是设计使然,因为这个位置的目的只是存放锁文件和其他运行时相关的东西,本质上不占什么显著空间。如果是这样的话,回退到使用这个目录就让人感觉很不妥。

+1;这个问题在 WSL2 上更严重,那里 XDG_RUNTIME_DIR 被设成了 /mnt/wslg/runtime-dir,而且权限是坏的。能不能在未来的版本里去掉 XDG_RUNTIME_DIR,默认用 /tmp?

我最近在 GitHub Actions 上用 Nix 时遇到了这个问题。跑 go test 的时候空间耗尽了,这说不通,因为我们的项目也没那么大。

调查了一番之后,我发现 NIX_BUILD_TOP 被设成了 /run/user/1001,而在 GitHub runner 上这是一个小于 700 MB 的挂载点。

我花了很长时间才找到这个原因。

我不知道正确的答案是什么,但这确实非常出人意料。

+1,我们仍然因为这个遇到 ENOSPC。把 $TMPDIR 设成 $XDG_RUNTIME_DIR 从 XDG 规范的角度看是错的,实践中也造成了一堆问题。

老实说,我找不到哪怕一条评论认为 NixOS 现在的做法是对的,而且所有评论似乎也都同意在 nix-shell 里 $TMPDIR 应该用 /tmp。

老实说,我很惊讶这个 issue 到现在还没被修复,而当我看到最初创建这个 issue 的日期时,惊讶变成了震惊:2014 年 11 月 15 日。

这个 issue 已经开了快 10 年了,所有受影响的用户对于该怎么处理似乎几乎一致认同,然而……它似乎就是被无视了?更离谱的是,GitHub 的“Stale Bot”不断把这个 issue 标记为“stale”,尽管它仍然是个大问题,用户于是不得不去评论来去掉那个状态,以防这个 issue 被关闭。(别让我开始吐槽我有多讨厌 Stale Bot,那可以单独写一篇文章了。)

我知道这未必能代表 NixOS 的每一个 issue,或者诸如此类,但它还是让我恼火——我已经在操作系统的好几个不同部分上遇到困难了,而这只是又一件本可以让我体验明显更好的事,但问题似乎就是被完全无视了。

不过,让我恼火的还不只是这个具体 issue 本身——更重要的是,这个 issue 在我看来说明“你必须在 nix-shell 里构建一切”这个原则……根本说不通?我已经被这样一件事惹恼了:它逼着你为了确定性构建去绕一堆弯子,而你其实根本不需要那个;而这件事还表明,它逼着你为了一个甚至都不具备确定性的东西去绕弯子!

在 NixOS 里,如果你在 shell 外面设置了一个环境变量,然后调用 nix-shell,那个环境变量会被保留!所以你可以毫不费力地影响这个本应具有确定性的 shell 的环境。是的,我知道,你可以给 nix-shell 传 --pure 来避免这种行为,但如果这整套 nix-shell 构建系统的目的就是阻止任何非确定性的东西,那为什么它不是默认行为?在我看来,“确定性构建”这个原则只被半吊子地执行着——刚好到足够碍我事的程度,却又不足以真正给我带来什么保证。

这一切不过是压垮骆驼的又一根稻草罢了,我想。

不管怎样,我在 configuration.nix 里把 environment.sessionVariables.TMPDIR 设成了 /tmp,重建了系统,这一次似乎真的修好了。那就继续看看下一个问题会怎么迎面给我一拳吧。

幸运的是,我接下来尝试的几件事倒没那么可怕。不过,这也不是说它们就容易。

(原文较长,此处译出前 6000 字,完整内容请点「打开原文」。)

正文由 探How 从来源站点 RSS 同步,内容未经改写;遇到排版缺失或需要图片、视频时请以原文为准。

打开原文
去社区讨论 →