For the complete documentation index, see llms.txt. This page is also available as Markdown.

FreeBSD 本月动态

在本期的 Ports Report 专栏中,Frederic Culot 指出 FreeBSD Ports 将在 2014 年 8 月 21 日迎来 20 周年纪念。借此纪念,我近期采访了它的创建者 JORDAN HUBBARD

DL:是什么促使你创建 Ports 系统?你的设计目标是什么?例如,当时在 BSD 或其他 UNIX 变体上是否有可用的软件管理工具?你的设计想要解决哪些问题?

JH:我创建 Ports 很大程度上是作为一个简单的自动化实验。当时我忍不住注意到,我往往会给任何新的 FreeBSD 安装添加的所有软件都遵循相同的基本步骤:从某个已知位置抓取源码 tar 包,解压到工作目录,配置,构建,安装。

这个过程当时普遍被认为“够简单”,没人真正尝试过自动化它——至少不是那种简单适配各种源码位置(以及软件“原生”使用的配置和构建流程,而不是把整个软件重新打包进某个封闭生态)意义上的自动化,这让我感到好奇:为什么我们被迫记住所有那些源码 tar 包的各种 URL,并且每次新装 FreeBSD 时都要手动重复执行同样的抓取/解压/配置/构建步骤——常常还重复很多次?这并不算特别难,但也属于那种计算机发明出来就是为了消除的重复性任务!

所以动机大致就是这样。我只是想看看这个过程能不能自动化,而我使用 make(1) 是因为它本身基本上就是为这类任务设计的——自动化重复性工作。我只需要编写 make 宏,让人能相对简洁地创建 Port 的 makefile。

我也没有带着任何“设计流程”来开展这个实验——我只是不停地移植各种软件,专挑那些比较不寻常、难移植的软件来测试整体概念,并不断改进 make 宏以应对沿途遇到的各种挑战。等到了 200 个 Port 左右,我断定概念已经得到充分验证,好奇心也彻底满足,于是找到 Satoshi Asami——他已经贡献了大量 Ports,而且看上去比我更有动力把这件事推进下去。他才是真正把 Ports bootstrap 成今天这个样子的人。他们不是平白无故叫他第一任“portsmeister”的!

DL:你对 Ports 的长期愿景是什么?例如,你预期这会成为在 BSD 上安装软件的事实标准方式吗?还是你把它视为某个更长期计划的第一阶段?

JH:我不确定自己是否对 Ports 本身有过任何长期愿景,但我对“软件饲养”(software husbandry)这个概念——我喜欢这么称呼它——确实有一些长期目标。Ports 以及相应的包管理工具(我也写了它的第一版)很大程度上只是这些目标的组成部分。

我真正想要的是让最终用户能轻松发现并安装第三方软件,而“把它弄到他们机器上(或再卸载掉)”的那些繁琐细节抽象掉,以至于他们只需要启动某个包浏览工具,点击合适的分类(或者在搜索框里搜索),然后从菜单中选择想要的项目来安装(或卸载)即可。我还希望构建第三方软件的框架对开发者完全暴露并可访问,因为显然得有人喂养流水线的另一端,才能有第三方软件集合可用。我知道除非这个集合相对容易添加和更新,否则它不会成长。这些目标有的实现了,有的没有,还有的只是带着附加条件实现——这正好可以引出你的下一个问题!

DL:以你今天的所知来看,有什么是你希望在 Ports 系统的设计中加入却没有加入的吗?

JH:哦,当然有!我大概能列出几百件希望当初采用不同做法的事情,但为简洁起见,我只列出我认为最重要的几条:

  1. 我希望我没有使用 make(1)。我对 Berkeley make 宏系统了如指掌,所以当时用起来非常顺手,但我没有考虑到的是,makefile 也非常难以被程序化操作,所以你无法轻松遍历整个集合,在你想重新整理/重构或者对整个 Port 集合做任何真正的分析时进行大规模改动。这也让“自动化的自动化”(比如“傻瓜化 Port 创建工具”等)变得困难得多,因为 makefile 并不便于自省。作为一种数据描述格式,它有很多不足。

  2. 使用 make(1) 还打破了一条我当时并没有真正意识到的基本原则(嘿,那是 90 年代,我们还都很理想主义)。它把主动数据和被动数据混在一个地方,或者用英语的比喻来说,描述一个 Port 及其动作的“动词”和“名词”在同一份元数据里纠缠不清。这让审计一个 Port 在做什么——或者在构建时它希望预先做什么——变得实际上不可能。由于很多 Port 还需要至少以 root 身份执行它们的安装阶段,从安全角度看这是一个非常糟糕的设计选择。一台专门的 Port 构建机总是可以在 chroot 或 jail 沙盒里干活,但大多数用户只是直接在自己的机器上以 root 身份执行 make install,即便一个 Port 不是恶意的,它仍然可能因为构建上的缺陷导致意想不到的后果。

  3. 我把安装软件的过程和构建软件的过程混在了一起。当时看来,构建过程的最后一步逻辑上就该是支持软件的实际安装(否则意义何在?),但这其实没有正确区分构建框架的职责和包管理框架的职责。我后来在包工具和 Ports 之间做了一些拼凑的阻抗匹配,使得 make installmake package; pkg_add <生成的包> 都能得到相同的结果并留下相同的注册信息,但我当初应该做的是让 Ports 的输出始终是包,永远不直接接触宿主系统,把安装这件事完全交给包管理系统。

DL:展望未来,你对软件管理有什么看法?你认为 Ports 是这个未来的一部分吗?

JH:嗯,如果我今天要重新来过,我大概会用某种机器可解析的格式来描述一个 Port,以便对整棵树的大规模修改能少一些痛苦。我会让 Ports 更加面向对象一些(带继承和混入)。我会让构建机制始终在某种沙盒里执行,并提供多种可能的目标,例如不一定是同一台宿主机架构或发布版本的构建器。最终产物始终是一个包,并且我也只允许包在安装(或卸载)时执行一组有限的动作,例如不允许它们执行任意的、不可审计的 shell 命令。这意味着一个包的所有元数据本质上都是“被动的”,直到包管理机制显式作用于它,包管理机制则可以再实现各种关于哪些包(或用户)可以做哪些事情的安全策略。

我也会更多地思考被打包软件的实际运行时环境。这已经不是 90 年代的那个互联网了,显然,我们不能再任意信任第三方软件——编码错误、恶意行为者、整个安全环境都变了。这意味着我们需要为安装在我们机器上的一切建立可溯源性,而即便建立了溯源,我们仍需要把它们彻底沙盒化,让它只能访问自己的数据,或者我们谨慎授权它访问的数据,而不是放任它用我们自己的权限乱跑,更糟的是在系统上乱跑。所有这些要求都会影响软件的审计、构建、签名、分发和安装过程,FreeBSD 所使用的所有工具都需要相应演进。

DL:关于 Ports 或软件管理还有其他有趣的事或轶事吗?

JH:如果说 Ports 这样的软件生态教会了我们什么,我认为那就是我们对软件饲养的一些根本观念需要彻底重新思考。如果你看看今天的 Ports,它已经是一片由相互依赖的独立软件和版本组成的森林,其中许多还互不兼容,即便是井井有条的废料场也还是废料场。它只会越变越大、越难驾驭,我说不准它还能向外扩展多远才会开始承受不住自身的重量。有人可能会说这种坍塌已经在发生。

此外,让“把东西任意地连接在一起”变得轻而易举,也纵容了软件行业一些最糟糕的做法延续下去。把大量互不相干的软件组件链接到一个地址空间里组成一个应用——不管它是瞄准某个嵌入式角色,还是运行在桌面这样功能丰富的环境里——可能既容易又相当诱人,尤其当你赶着交付的时候,但它显然也很脆弱、充满潜在风险。最近 OpenSSL 的事件已经充分证明了这一点,仿佛我们还需要更多证明似的;而且尽管 Heartbleed 漏洞带来的余波已经足够重大,我认为我们也只看到了冰山一角。我们将会看到更广泛传播的漏洞,在行业停止把动态库和可加载模块看作“方便的软件集成电路”、更多地视为需要到处使用光耦隔离的可怕东西之前,我们还会承受更多痛苦。

像 OpenSSH 和 Postfix 这样的软件包多年来一直使用多进程、权限分离的模型,但我们需要想办法让所有人都把这当成理所当然,即便这需要创建快速且安全的 IPC 机制(以及让这些机制更易用的便捷 API)来促成。

在那种世界里,像 Ports 这样的软件管理框架完全有可能成为推动此类最佳实践而非当前最糟实践的力量。但愿如此!


Dru Lavigne 是 FreeBSD 基金会董事,BSD 认证小组主席。

最后更新于