在 Mac 终端或者 Linux 服务器里配过环境变量的人,肯定都见过这串奇怪的路径。

/bin/usr/bin/usr/local/bin

中间还夹着 /sbin/usr/sbin

刚学命令行那会儿,我一直以为这是某种精密的系统设计。

大学操作系统课和各种考证教材,也确实是这么教的。

教材上写得头头是道,说 /bin 存的是系统启动和急救时「最关键的底层命令」,比如 lscpsh 。就算其他磁盘挂了,只要根目录还在,你就能靠 /bin 把系统救回来。

/usr/bin 里的 usr ,放的是日常给普通用户用的工具,启动时不靠它们。

这套说法听起来特别有计算机先驱那种严谨的工匠味儿。

大家也就这么规规矩矩地背了几十年。

直到后来 BusyBox 的维护者 Rob Landley 实在忍不住了,去翻了当年的源码和开发邮件,大家才发现全被忽悠了。

压根没有什么深思熟虑的系统分层。

肯·汤普逊和丹尼斯·里奇当年之所以建了个 /usr/bin ,纯粹是因为穷。

1971 年,俩人在一台 DEC PDP-11 机器上写 Unix 第三版。

那台机器上挂着两块 RK05 磁盘

那块盘多大呢,1.5 兆,也就是 1.5MB。

当时 Unix 的内核代码和常用命令越写越多。肯·汤普逊把操作系统内核、启动文件和常用工具一股脑往第一块盘的根目录 / 里塞。

塞着塞着,第一块盘满了。

系统写了一半,磁盘见底了,总不能停工吧。

打开网易新闻 查看精彩图片

他们手头正好还有第二块 1.5MB 的磁盘。这块盘原本挂在 /usr 目录下,专门用来放实验室几个同事的个人文件,所以才叫 usr ,就是 user 的意思。

肯·汤普逊看着第二块盘还空着大半,没做任何设计,直接在 /usr 底下建了个目录叫 /usr/bin

操作朴实无华。

第一块盘装不下的命令,顺手扔进第二块盘的 /usr/bin 。第一块盘装不下的函数库,顺手扔进 /usr/lib

搞完之后,在每个用户的环境变量里加一句 $PATH=/bin:/usr/bin

磁盘报警解除,收工,继续干活。

当时 Unix 还不支持跨物理盘的软链接。既然第一块盘满了,溢出来的东西就塞给第二块盘,整个过程连五分钟都没用上。

好玩的事情在后面。

后来的计算机硬件发展太快了。磁盘从 1.5MB 一路狂飙到几百 G、几个 T,当年那台 PDP-11 早被送进了博物馆。

但当年那个因为硬盘装不下随手打的临时补丁,却被所有人当成了圭臬。

后来的开发者看到系统里躺着两个 bin 目录,开始本能地脑补背后的深刻哲理。

有人觉得这是为了方便做网络无盘工作站,根目录放本地, /usr 放远程挂载。

有人觉得这是系统权限隔离的最佳实践。

甚至连 usr 这个单词,都被硬生生编成了一个缩写。

打开网易新闻 查看精彩图片

结果这种强行脑补,在后来的工程实践里把大家坑惨了。

没人能分清到底什么算「核心命令」,什么算「普通工具」。

有的 Linux 发行版把 ping 塞进 /bin ,有的塞进 /usr/bin 。很多命令还会偷偷依赖动态库,比如一个躺在 /bin 里的急救工具,编译时无意中链接了 /usr/lib 里的某个库。

等系统真崩了进单用户急救模式, /usr 没挂上,根目录下的急救命令当场报依赖丢失,直接瘫痪。

这套大家小心翼翼维护了半个世纪的优雅架构,最后成了各个发行版启动脚本里最难打扫的烂摊子。

最近这几年,各大主流 Linux 发行版终于决定不陪着演戏了。

Fedora、Debian、Arch Linux、Ubuntu 陆续推行 usrmerge

解决办法简单直接,把 /bin/sbin/lib 全部做成软链接,直接指向 /usr/bin/usr/sbin/usr/lib

打开网易新闻 查看精彩图片

折腾了五十年,所有人最终发现,它们本来就该在一个文件夹里。

很多我们平时在终端里奉为标准的规范,只要往回扒三十年,大概率就是当年某个程序员在凌晨两点,面对一块快要爆掉的 1.5MB 破硬盘时,随手打的一个偷懒补丁。

下回在终端里配 $PATH 抓狂的时候,别急着怀疑自己的系统设计水平。

可能只是半个世纪前,有位祖师爷的磁盘真的装不下了。