在 Linux/macOS 系统的根目录 / 下,有这样几个目录:bin、sbin、usr/bin、usr/sbin。
青小蛙一直搞不懂为什么要这样,直到看了 BusyBox 的核心开发者 Rob Landley 在邮件列表中吐槽这件事,才终于明白为什么,堪称 Linux 冷知识呀。@Appinn

说起来,这个冷知识的来源,也十分的冷门。在 2010 年(是的,16年前),BusyBox 的核心开发者 Rob Landley 在邮件列表中直接提到:
我发现 busybox 将其链接分散到这 4 个目录中,是否存在一条简单的规则来决定每个链接位于哪个目录?
例如,我看到 kill 命令在 /bin 目录下,而 killall 命令在 /usr/bin 目录下……我不明白。
弄清楚这背后的逻辑是什么。
为什么要分这么多目录?它们到底是干什么的?
答案有些简单,也有点出乎意料,这不是特意设计出来的,而是又一个历史遗留。
这要从 1970 年代说起
Unix 诞生于 1970 年代,运行在 PDP-11 这样的古老机器上。
当时的硬盘有多大?1.5MB。

最开始,整个系统都装在根文件系统 / 里,其中包括:
/bin:基本命令/sbin:系统管理命令/lib:库文件
后来系统越写越大,磁盘装不下了。
第二块硬盘
于是需要第二块硬盘,并挂载到 /usr 目录下。
(与 Windows 不太一样,没有 C 盘、D 盘。在 Linux 下,你可以把第二块磁盘挂载到 /usr 等任何目录下)
此时,就出现了四个路径:
/bin、/sbin:必须在系统早期启动时就能用的命令/usr/bin、/usr/sbin:系统启动完成、挂载/usr后才能用的命令
这解决一个当年真实存在的先有蛋还是先有鸡的问题:
先挂载磁盘才能用 mount 命令,但 mount 又在磁盘里 😂
为什么这种划分在今天已经不合理了?
Rob Landley 觉得,这套规则在现代设备,以及现代 Linux 中,已经没有意义了。
临时根文件系统
现代系统有临时根文件系统(initramfs / initrd)了,这是在内核启动后、真正的根文件系统挂载前,用来“过渡启动”的一个小型 Linux 系统。

启动早期依赖的问题早就由临时根文件系统解决了,所以不再需要靠目录结构来“区分启动阶段”,
共享库
共享库是一份可以被多个程序同时使用的公共代码。它可以是:
/lib/libc.so.6
/usr/lib/libc.so.6
/usr/lib/libstdc++.so.6
没有共享库之前:
在 早期 Unix(1970s),程序是这样的:
- 全部静态链接
- 每个可执行文件里:
- 都自带一整套函数代码
- 比如字符串处理、IO、数学函数
举个极端但真实的例子:
ls 里有一份 printf
cp 里有一份 printf
mv 里也有一份 printf
这种方式的特点是:
- 程序彼此完全独立
/bin和/usr/bin里的程序,可以来自不同磁盘、不同版本- “只升级
/bin,不动/usr”在技术上是可行的
有了共享库之后:
好处巨大,节省磁盘空间、多进程共享内存、修一个漏洞,全系统生效。
但代价是程序和库“绑死”了,如果 ls 程序需要 libc.so.6 这个库,但 /usr/lib/ 目录下只有 libc.so.5,那么 ls 就无法运行。
这意味着,在共享库成为主流之后:
/bin里的程序/usr/bin里的程序/lib、/usr/lib里的库
已经不可能再被当成“可以独立升级、独立维护的部分”。
而 /bin、/usr/bin 这样的目录分离设计,正是建立在这一历史前提之上:
它们可以相互独立,甚至部署在不同的磁盘之上。
廉价的硬盘
对比 1970 年代,现在的硬盘已经廉价太多太多了,容量也不知道翻了多少倍。当然如今的价格比起前两年又涨了一点,但拉宽时间段,还是非常廉价。技术上进行分区调整也不是问题了。
当磁盘容量、分区调整都不再是问题时,当年为了“省磁盘”而产生的目录分离,也就失去了现实基础。
历史惯性下的新规则
你每天在用的 Linux 目录结构,其实是在为 1970 年代的一块 1.5MB 硬盘继续买单。
在历史惯性下,人们不断给这些目录强行赋予新定义,比如:
/:系统原生内容/usr:发行版附加内容/usr/local:本地安装的软件/opt:第三方商业软件- 各发行版对
/tmp、/var/tmp、/usr/tmp的规则还互相不一致
这最终导致缺乏统一逻辑、增加了复杂度,本质上是在为一个早已消失的历史问题“打补丁”。
在现代 Linux 系统中,这样的目录结构已经几乎没有技术必要,却因为惯性和“标准”被延续至今。
原文:https://www.appinn.com/linux-bin-usr-directory-history/