@
ityspace #47
@
424778940 #65
@
Jirajine #51
作为发行版来说,我认为现阶段 NixOS 是不够严肃的,定位大致可以接近于弱化版的 Arch 。作为语言的 Nix 和作为包管理的 Nixpkgs 也不能直接拿来对比的,但是这三个经常被混在一起。比如 NixOS 官网提到的三个特性关键词 Reproducible/Declarative/Reliable 实际上分别是描述 Build ( Nixpkgs )/Language ( Nix )/OS ( NixOS )的。(另外官方的正式名称 Nix 既是语言,又是包管理器,Nixpkgs 指的是软件仓库)
按时间来说,我印象是先有的 Nixpkgs 的想法,为此设计了 Nix 语言,最后才有的 NixOS 。早期(至少十年前了) Nixpkgs/Nix 的文档实在是太简陋了,大部分时间我都是看着代码去猜的……当然现在易用性好了很多,只是我个人的评价是,Nix 系的设计目标是有可借鉴之处的,但是实现方式和哲学我不是很认可。
当年我被 Nixpkgs 吸引的原因是它希望用新的方式(在当时是很超前的思路)*同时*解决包管理器常年存在的几个问题:一是多版本共存,二是依赖解析,在此基础上顺便提供两个新特性:支持原子操作和回滚且无需依赖特定文件系统,再就是 Reproducible 构建。实现方式上,用的是现在被很多包管理借鉴的叫做 Content-addressable storage 的存储后端,以及类似沙盒化的构建过程(主要是记录依赖树而非权限限制)。
换个简单的说法,这个包管理的思路就是:记录依赖树上每个包的版本,同名包不同的版本会各存一份,相同版本也只存一份,而目标应用的执行环境(沙盒)中只有用得到的特定版本的依赖。这是个很理想化的设计,也存在很现实的问题。根据 Debian 过去十多年的构建经验,符合 Reproducible 构建标准(二进制一致)的包的占比一直在 85% 左右(构建这个行为会引入包依赖之外的变量)。Nixpkgs 意义上的 Reproducible 更接近于容器镜像可移植 Portable 的概念,即每次构建可能不同,但可以相互替换。
对于开发者来说,一般不关心打包的事情,但多数都会提供构建脚本。对于打包者来说,针对特定系统的打包希望尽量标准化,配置尽可能简单,原作者的构建脚本能拿过来用最好。对于包管理器来说,依赖最好是清楚写明的而不要是推断的。在 Nixpkgs 的设计者来说,当时没有合适的工具,所以想要创建一门新的语言,功能需求至少有几个:有脚本的灵活,声明式的写法以及模板化的生成能力。
至少在 Nixpkgs 层面,我是很欣赏设计思路的。到了 Nix 这门语言的层面,我的能力不足以做出准确的论断。仅从用户的角度上说,学习成本和易用性门槛都是相对比较高的。我个人认为 Nixpkgs 可以和 Gentoo portage 相媲美,都可以作为非常好的构建平台。
当包管理器想要往发行版方向发展时,限制就显现出来了。我一直说 RedHat/Debian/Suse 系是相对严肃的发行版,主要是因为它们都有足够的维护者。Nix 目前官方仓库的维护水平差距还是比较大的,而且可以遇见由于用户基数和门槛的限制,这个改善过程会很艰难。
另一方面我认为 NixOS 在发行版或者操作系统的理解定位上有点走偏了,就好比 Nixpkgs 是很好的锤子,但是 NixOS 太想把发行版塑造成钉子的形状。而且无论是 Windows/Linux/macOS 经过这么多年的发展,比较明显的共识是操作系统应该追求 Immutable 而不是 Reproducible 。这方面 NixOS 的实现方式永远比不上基于文件系统( layered )的效果,所以 NixOS 只能宣传自己 Reliable 却无法说自己是 Immutable 。
再就是用户数据理应和系统分离,应用程序理应和配置分离。NixOS 推崇的把用户、配置纳入进来的思想在我看来耦合有点过深了。不是说这样做不好,只是不太符合我个人的 Linux 哲学认知。