在 Mac 终端或者 Linux 服务器里配过环境变量的人,肯定都见过这串奇怪的路径。
/bin、/usr/bin、/usr/local/bin。
中间还夹着 /sbin 和 /usr/sbin。
刚学命令行那会儿,我一直以为这是某种精密的系统设计。
大学操作系统课和各种考证教材,也确实是这么教的。
教材上写得头头是道,说 /bin 存的是系统启动和急救时「最关键的底层命令」,比如 ls、cp、sh。就算其他磁盘挂了,只要根目录还在,你就能靠 /bin 把系统救回来。
而 /usr/bin 里的 usr,全称是「User System Resources」,放的是日常给普通用户用的工具,启动时不靠它们。
这套说法听起来特别有计算机先驱那种严谨的工匠味儿。
大家也就这么规规矩矩地背了几十年。
直到后来 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 这个单词,都被硬生生编成了一个缩写,叫「User System Resources」,搞得跟真的一样。

结果这种强行脑补,在后来的工程实践里把大家坑惨了。
没人能分清到底什么算「核心命令」,什么算「普通工具」。
有的 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 抓狂的时候,别急着怀疑自己的系统设计水平。
可能只是半个世纪前,有位祖师爷的磁盘真的装不下了。