帖子内容
一般的 Linux 包管理器都做不到这两件事: 1. 一个软件包的多个版本共存。当两个软件包都依赖第三个软件包时,只能选一个版本装,不能装两个版本分别给两个软件包用。 2. 非 root 用户方便地安装喜欢的软件版本和所有依赖。如果系统装了 vim 8.2,非 root 用户想用 vim 9.0 就只能自己找来所有依赖,编译安装,没有包管理器这样方便的方案。 为什么一个软件在整个系统中只能装一个版本呢?存储不同版本的软件以及依赖,让它们各用各的依赖,听起来并没有本质上的困难。我最近研究了一番 Nix,它看似可以解决这种需求,但实际上它使我意识到了这里实际的困难。 各种软件里面都有写死的其他软件的名字或路径(一般不带精确版本),Nix 打包时改写了这些内容,为它们加上了精确版本。这样一来,两个软件可以分别调用自己的依赖,互不干扰,这些依赖也都不会暴露给最终用户。最终用户如果也想用这个依赖,要自己指定想用哪个版本(可以是和这两个软件用的都不同的第三个版本)。 但是 Nix 并没有改掉一切,例如 git commit 会自动调用 vi 来编辑提交信息,git diff 会自动调用 less 来分页,Nix 并没有将 vi 或 less 视为 git 的依赖并锁定版本。我想这是比较合理的,因为用户会希望用自己喜欢的 vi/vim 或 less 版本,而不是 git 这个软件打包时锁定的某个版本。虽然 git 提供了配置选项来自定义使用的命令,但默认值也是很重要的。如果每个软件都必须自定义一番才能用上自己在全局安装的 vim 或 less,体验应该会很差。 还有一个小问题是家目录中的配置文件和数据,如果系统中装了多个版本的 vim,却共用一个家目录下面的 .vimrc 和 .viminfo,很可能会出现问题。如果试图让它们用不同的家目录,恐怕不仅不会解决问题,反而可能会更混乱。 所以这里存在本质上的矛盾:所有软件的所有依赖都被锁定和相互隔离的话,好处是省心,依赖都是开发者预期的版本,自己写的程序随便起名也不会被意外调用,坏处是用不上自己喜欢和熟悉的版本,家目录中的数据文件可能不支持不同版本的程序读写,以 daemon 形式存在的服务可能无法工作(因为 client 和 server 版本不一致,例如 git clone 时 git 自己的 ssh 版本可能无法连上 control master)。更高层的应用程序可能还好,对于底层的各种基础工具(git vim curl less ssh 等),看来想实现不同版本共存确实有难度。