字数 1317,阅读大约需 7 分钟
你见过 bin 目录吗?你见过 usr/bin 目录吗?为什么它们看起来如此相似却又被分开存放?这背后是精妙的设计,还是一场历史的意外?
在 Linux 或 macOS 系统的根目录 / 下,你总会见到几个让人有些困惑的目录:/bin、/sbin、/usr/bin 以及 /usr/sbin。
很多人可能都有过类似的困惑,直到看到 BusyBox 的核心开发者 Rob Landley 在一封古老的邮件列表中的吐槽,才恍然大悟。原来,这堪称是 Linux 世界里一个有趣的“冷知识”。

这个故事的源头确实冷门。时间回到 2010 年,BusyBox 的开发者 Rob Landley 在邮件列表中直接发问:
“我发现 busybox 将其符号链接分散到这 4 个目录中,是否存在一条简单的规则来决定每个链接应该放在哪里?”
例如,我看到 kill 命令在 /bin 目录下,而 killall 命令却在 /usr/bin 目录下……我实在搞不懂。我想弄清楚这背后的逻辑是什么。
为什么要分这么多目录?它们到底是干什么的?
答案既简单又出乎意料:这并不是某种精心设计的最佳实践,而纯粹是 又一个历史遗留问题。
这要从 1970 年代说起
Unix 诞生于 1970 年代,运行在像 PDP-11 这样的古董机器上。当时的硬盘有多大?答案是惊人的 1.5MB。

底部是PDP-11/40 CPU,顶部安装了一个TU56双磁带DECtape驱动器。
最初,整个操作系统都安装在根文件系统 / 里,其中就包括几个核心目录:
/bin:存放最基本的用户命令。
/sbin:存放系统管理命令。
/lib:存放系统库文件。
随着系统功能越来越丰富,软件越来越多,一个现实的问题出现了:最初的硬盘装不下了。
第二块硬盘
解决方案就是增加第二块硬盘,并将其挂载到 /usr 目录下。
(这与 Windows 的盘符概念不同。在 Linux 系统中,你可以将额外的磁盘挂载到像 /usr 这样的任何目录下。)
于是,四个路径的雏形和分工便诞生了:
/bin、/sbin:存放必须在系统早期启动时就能使用的命令。这些命令位于根文件系统,确保在/usr挂载前可用。
/usr/bin、usr/sbin:存放系统启动完成、成功挂载 /usr 磁盘后才能使用的命令。
这个设计巧妙地解决了一个“先有鸡还是先有蛋”的真实困境:
先挂载磁盘才能用 mount 命令,但 mount 命令本身又存放在磁盘里 😂
所以,像 mount 这样的关键命令必须放在根文件系统的 /bin 或 /sbin 中,否则系统将无法挂载其他磁盘。
为什么这种划分在今天已经不合理了?
Rob Landley 认为,这套诞生于半个世纪前的规则,对于现代设备和现代 Linux 发行版而言,已经失去了其技术必要性。
临时根文件系统
现代 Linux 系统普遍采用了临时根文件系统(initramfs / initrd)。这是内核启动后、真正的根文件系统挂载前,用于“过渡启动”的一个小型 Linux 系统。

启动早期对硬件驱动、磁盘挂载工具的依赖,早就由这个 initramfs 临时系统解决了。因此,不再需要依靠目录结构来区分命令的“启动阶段可用性”。
共享库的普及
共享库是一份可以被多个程序同时调用的公共代码,例如 /lib/libc.so.6 或 /usr/lib/libstdc++.so.6。
在没有共享库的早期 Unix(1970s):
程序全部采用静态链接。每个可执行文件内部都自带一整套它需要的函数代码(比如字符串处理、输入输出函数)。这意味着:
- 程序彼此完全独立。
/bin 和 /usr/bin 里的程序,理论上可以来自不同的物理磁盘、甚至是不同的软件版本。
- “只升级
/bin 下的程序,而不动 /usr 里的内容”在技术上是可行的。这正是目录分离设计的物理基础。
在共享库成为主流的今天:
共享库带来了巨大好处:节省磁盘空间、多进程共享内存、修复一个库的漏洞能使所有依赖程序受益。
但代价是程序和库文件被“绑死”了。如果 /bin/ls 程序依赖于 libc.so.6,而 /usr/lib/ 目录下只有 libc.so.5,那么 ls 命令将无法运行。
这意味着,在共享库时代:
/bin 里的程序
/usr/bin 里的程序
/lib、/usr/lib 里的库
已经不可能再被当作“可以独立升级、独立维护的部件”。目录分离所依赖的“物理独立性”前提已经瓦解。
廉价的存储
与1970年代相比,如今的硬盘容量已呈指数级增长,价格却变得极其廉价。存储空间和分区调整早已不是制约系统设计的瓶颈。
当磁盘容量不再是问题时,当年为了“节省每一MB空间”而产生的目录分离设计,也就失去了其最根本的现实基础。
历史惯性下的新“规则”
你每天使用的现代 Linux 目录结构,在某种程度上,仍在为 1970 年代那块 1.5MB 的硬盘“买单”。
在强大的历史惯性下,社区和各大发行版不得不为这些目录强行赋予新的、更抽象的定义,例如:
/:存放系统原生、必不可少的内容。
/usr:存放发行版附加的、非启动必须的软件和数据。
/usr/local:存放本地管理员编译安装的软件。
/opt:存放大型第三方商业或独立软件包。
- 各发行版对
/tmp、/var/tmp、/usr/tmp 的语义和清理规则还常常不一致。
这最终导致了一个结果:缺乏真正统一、清晰的逻辑,并增加了系统管理和理解的复杂度。本质上,我们是在为一个早已消失的技术限制不断地“打补丁”。
在现代 Linux 文件系统中,/bin、/sbin、/usr/bin、/usr/sbin 的严格分离已几乎没有技术上的必要性,却因为向后兼容的“标准”和强大的历史惯性被延续至今。理解这段历史,能帮助我们更辩证地看待那些看似理所当然的“规范”。如果你想了解更多类似的底层知识,欢迎到 云栈社区 与其他开发者一起交流探讨。
原文:https://www.appinn.com/linux-bin-usr-directory-history/