所有软件包都已安装
摘要
Omnibin 是一个 FUSE 文件系统,提供按需访问 nixpkgs 中所有二进制文件的功能,消除了传统软件包安装的需要。
<p><a href="https://lobste.rs/s/wqzbpw/every_package_is_already_installed">评论</a></p>
查看缓存全文
缓存时间: 2026/09/25 09:11
# 每个软件包都已安装
来源:https://fzakaria.com/2026/09/24/every-package-is-already-installed
> **简而言之:** omnibin (https://github.com/fzakaria/omnibin) 是一个 FUSE 文件系统,它将**nixpkgs 曾交付过的每个二进制文件**都放入你的`$PATH`环境变量中。无需安装任何东西。无需构建任何东西。直到某个程序实际读取文件前,磁盘占用为 0 字节。😈
现在是 2026 年,为什么我还在逐个安装软件包?11 是的,我在观看了 DHH 在 RailsConf 2026 上的主旨演讲 (https://www.youtube.com/watch?v=vDjW_dRyKXY) 后受到了一点启发。我对软件包管理也有同感。

为什么我必须遵循向`configuration.nix`添加包、运行`nix-shell`或屈服于地狱般的`nix-env -iA`操作的仪式?
Nix 赋予我们并行安装包而没有冲突的能力。为什么我必须选择要安装哪些包?
为什么我不能拥有所有包?
如果机器本身就包含所有包呢?
```
$ nix run github:fzakaria/omnibin
omnibin: tree at /run/user/1000/omnibin, cache at /home/you/.cache/omnibin
$ ls /omnibin/bin | wc -l
51468
$ python3 --version
Python 3.14.6
$ [email protected] --version
Python 3.6.2
```
这意味着在我的`$PATH`中有超过**五万个**22 实际上,该树中有 881,933 个二进制文件,但`ls /omnibin/bin`仅列出每个二进制文件的最新版本。带版本号的形式仍然可用,但未被列出。顶级二进制文件,时间跨度从 2013 年到 2026 年,由 Nixpkgs (https://github.com/NixOS/nixpkgs) 构建,按需可用,无需安装任何东西。

这是 Nix (https://nixos.org/) 的魔力 🧙♂️,但它并不局限于 Nix。
大家似乎仍然喜欢 Docker (https://www.docker.com/) 和 OCI (https://www.opencontainers.org/),为什么我还要选择使用哪个基础镜像?为什么我不能拥有所有基础镜像?
```
# syntax=docker/dockerfile:1
FROM fmzakari/omnibin:latest
COPY <<'SH' /demo.sh
[email protected] -c 'import sys; print(sys.version.split()[0])'
jq --version
[email protected] --version | head -1
SH
CMD ["bash", "/demo.sh"]
```
这是终极的智能体运行环境吗?这是一个从一开始就包含一切的容器。尝试一下 fmzakari/omnibin (https://hub.docker.com/r/fmzakari/omnibin)。
```
$ docker build -t example .
$ docker run --rm --device /dev/fuse --cap-add SYS_ADMIN example
3.6.2
jq-1.8.1
gcc (GCC) 10.2.0
```
当然,我不能忘记我们的 NixOS 朋友们。你不再需要策划你的`environment.systemPackages`或`home.packages`,你可以直接拥有所有包。
```nix
{
imports = [ inputs.omnibin.nixosModules.default ];
services.omnibin.enable = true;
}
```
如果每个软件包都已安装,那“软件包管理”又是什么呢?
## § 这是什么魔法?
事实证明,Hydra 在 cache.nixos.org (https://cache.nixos.org/) 上的每个 narinfo 旁边都写了一个`.ls`文件,该文件以 JSON 格式描述了归档文件的内容:
```
$ curl -s --compressed https://cache.nixos.org/3n4qphl9s728sz8frmpqqrv9b1m87g68.ls | jq
{
"root": {
"entries": {
"bin": {
"entries": {
"python3": { "target": "python3.14", "type": "symlink" },
"python3.14": { "executable": true, "size": 14264, "type": "regular" }
```
这些元数据恰好是 FUSE 文件系统 (https://www.kernel.org/doc/html/next/filesystems/fuse.html) 的完美索引,该文件系统可以按需从缓存延迟获取 NAR 文件并解包。🤓
如果没有 nixpkgs-multiverse (https://fzakaria.com/2026/08/09/nixpkgs-multiverse-every-version-that-ever-existed)(它已经将 nixpkgs 历史记录中的任何`(属性,版本)`解析为 Hydra 在 cache.nixos.org (https://cache.nixos.org/) 上构建的存储路径),这一切都没有意义。
当你将两者结合时,你就得到了一个文件系统,它可以回答“`[email protected]`在哪里?”的问题,然后从缓存中获取并为你解包,而无需安装它。
我在不到十二分钟内爬取了所有`.ls`文件。🤯
一旦你拥有了它,文件系统本身就构建完成了:
```
$ ls /nix/store/2lb6nn8ivk1alhckv43n7734lqwbw7h9-python3-3.6.2/bin
2to3 idle pydoc python python3.6 python3-config pyvenv
2to3-3.6 idle3 pydoc3 python3 python3.6-config python-config pyvenv-3.6
idle3.6 pydoc3.6 python3.6m python3.6m-config
```
那是 2017 年的 CPython 3.6.2。那个`ls`命令*没有下载任何东西*,它是通过预爬取的索引回答的。
## § 请勿`ls`整个树
智能体是“一回事”。让它们有用是一回事。让它们在不安装任何东西的情况下有用是一回事。
如果你的智能体试图`ls /omnibin/bin`并对每个条目执行 stat 操作,它会非常糟糕。树中有 881,933 个二进制文件,对所有这些文件执行 stat 操作需要很长时间。

为了帮助智能体一点,`ls /omnibin/bin`仅列出裸名,每个可执行文件一个,每个解析为提供它的最新包。
带版本号的形式都可以解析,但未被列出。例如,`python3`解析为最新的 Python 3(撰写本文时为 3.14.6),但`[email protected]`解析为 2017 年的版本。
对于其他所有内容,有索引,它就在挂载点中:
```
$ sqlite3 /omnibin/index.db \
"SELECT attr, version
FROM bins
WHERE name = 'python3'
ORDER BY version"
```
那个用户体验有点粗糙,所以你也可以使用`omnibin` CLI 来查询索引:
```
$ omnibin which python3
/nix/store/gxzhl7aaiid7zp3y47jqqiq7zg5mqpwp-python3-3.14.6/bin/python3
$ omnibin which --all python3 | wc -l
610
$ omnibin which --all ffmpeg | head -2
[email protected] ffmpeg 0.4 MB /nix/store/0adpc3...-ffmpeg-3.1.7-bin/bin/ffmpeg
[email protected] ffmpeg 0.4 MB /nix/store/nhfgdv...-ffmpeg-3.2.4-bin/bin/ffmpeg
```
最后,有一个 /omnibin/README.md (https://github.com/fzakaria/omnibin/blob/b3acd8773a92b9acac9adc80997fac56ef9bac6b/src/mount-readme.md),它的全部职责就是告诉任何探索文件系统的内容:停止探索文件系统,转而查询数据库。🤖
## § 代价是什么?
到这里应该很明显了,但代价是你在首次访问时需要付出启动时间。
```
$ time [email protected] -c 'import sys; print(sys.version.split()[0])'
3.6.2
real 0m2.690s
$ time [email protected] -c 'print(6*7)'
42
real 0m0.035s
```
第一次运行花了 2.7 秒来获取 NAR 文件并解包,第二次运行是瞬时的,因为存储路径已经存在。
除此之外?没有其他代价了,这相当惊人。
对于任何长期运行的机器,你会期望你的`/nix/store`已经预热了你需要的软件包,因此首次访问的开销并不是什么大问题。
我记得最初让我震惊并让我对 Nix 感到折服的事情之一,就是看到 @burke (https://github.com/burke) 关于 comma (https://github.com/nix-community/comma) 的演示。能够在不“安装”它的情况下测试某个软件包,在某个特定的 nixpkgs 版本上;这是革命性的!我相信这是它的精神继承者,我希望能将我当初感受到的那种奇妙和惊叹感传递给他人,作为 Nix 强大力量的灯塔。
代码库位于 github.com/fzakaria/omnibin (https://github.com/fzakaria/omnibin)。
请负责任地使用`ls`。
相似文章
一个 Nix flake 统治一切
本文介绍 omniflake,这是一款 Nix 工具,它将数千个 flake 合并为一个输入,以简化依赖管理并提升基于 Nix 系统的用户体验。
Ohbin – 从GitHub安装工具的uv包装器
Ohbin是一款Python工具,作为uv的包装器,用于将GitHub发布版二进制文件直接安装到项目中,省去了手工制作包装包的需要。它通过pyproject.toml中的简单声明式配置,自动完成下载、SHA256验证、缓存和执行。
在Sailfish X(适用于Sony Xperia的Sailfish OS)上使用Nix
一份关于在适用于Sony Xperia设备的Sailfish OS上安装Nix包管理器的技术指南,涵盖文件系统布局、LVM分区以及F2FS相关注意事项。
nixpkgs-multiverse: every version that ever existed
nixpkgs-multiverse is a Nix flake that provides access to every version of every package that ever existed in Nixpkgs, allowing users to easily pin and mix historical package versions without multiple flake inputs.
nixpkgs-multiverse:快速模式
nixpkgs-multiverse 引入了一种快速模式,跳过 Nixpkgs 评估并直接获取包存储路径,从而可以更快地访问历史包版本。