冷知识:bin、sbin 与 usr/bin、usr/sbin 目录的由来

原始链接在: 冷知识:bin、sbin 与 usr/bin、usr/sbin 目录的由来 - 小众软件

在 Linux/macOS 系统的根目录 / 下,有这样几个目录:binsbinusr/binusr/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 系统中,这样的目录结构已经几乎没有技术必要,却因为惯性和“标准”被延续至今。


原文:

5 个赞

archlinux几年前就将/bin和/usr/bin合并了

又是一个“火箭宽度追溯到两匹马屁股宽度”的事

2 个赞

无所谓,我用NixOS

无用的知识又增加了。

这种故事可以多来点

不懂linx,不会打这个系统全名的人,,,哈哈。看完了,平时玩pve和nas,黑群晖,只进到这些目录,但好乱啊。win10以来,我是从win7直接到win11.这些新软件的目录也分了四五个地方了,以前就一个地方,后来有了64位两个地方,结果现在至少三个地方了吧。不过还算看得明白,不过感觉为什么不放在一两个目录就行了,有些非得放在AppData下安装程序。关键是原来的Program Files 两个目录放了绿色软件,动不动要个管理员权限就提示。放在d盘同样名称的目录也这样。最后我把一个smalltools(我专门放收集的小型绿色软件的文件夹,400+个工具),放在了d盘一个tools目录了。。。以前win7没有这回事!!

windows 这方面的规范也是挺好的
多用户系统嘛,所有用户都可以用的软件放在c盘 Program Files 下,所以全系统层面的安装需要弹 uac 窗口请求管理员权限
那些只有当前用户会用到的软件放在 AppData 下,是用户层面的操作,所以也就不需要管理员权限

顺带一提,现代电脑装 windows 已经完全可以不分盘了,更提倡使用用户的家目录来管理自己的文件

现在在用 archlinux ,好像很早就已经合并这些目录了,现在 /bin 和 /lib 都是 /usr/bin 和 /usr/lib 的软链接,用于存放所有由包管理器安装的程序和库。而 /usr/local/bin 用来存放用户自行安装的程序,防止扰乱包管理器的工作。这也是现代发行版的一个趋势吧

我的工作文件还习惯分盘放,也会把库目录里的几个文件迁移到d盘一个目录统一管理。大型软件也放在d盘一个目录统一。c盘主要放系统和集成度高的软件,用于备份。以前习惯分4个区。后来上ssd就分两个区,至少以前的ssd不建议分区太多。

每次安装完nginx/pgsql/php,都不知道它们的 程序、日志、数据文件 分别在什么目录。。。。
编译(对,往往还需要当场编译)时遇到库的版本不对,头大的要命,好不容易磕磕碰碰解决了,过几年重新在一个新的vps安装时,又忘了,或者出现的问题不一样了

一直奇怪,为什么不能让每个应用可以自己指定库的目录,避免与别的应用要求的库冲突

不用管这些啦,反正在终端里能运行就行。

为啥要编译?直接用包管理器安装系统软件仓库里面的就很简单。

发行版的软件库里不可能啥都有

原来Windows也可以不分盘了呀。用惯了Linux的目录树,Windows上传统的多硬盘只能CDEFG真的好烦。

nginx/pgsql/php 这些还算常见吧,库里面有。

硬盘也没便宜到那个地步吧。如果共享库没有必要的话,微信的体积也不会天天被喷了。随便哪个涉及到音视频的工具都带上几个版本的ffmpeg就够受的了。硬链接的ffmpeg大概80MB。

我认为有问题的是共享库的实现方式而不是共享库这个思路。这点我比较喜欢Nix的做法。但是这又绕回到本文了。NixOS没有完全遵循的FHS,而是在FHS基础上另外加了/nix。

需要特殊的配置,都要加不同的参数再编译。
linux应用对于这种扩展好像没发展出简单方便的真正“插件”机制

70年代到90年代,已经便宜了多少个数量级,更是从无到有的提升
90年代0.36M5元到现在10T1000元,又是从10元/M到了0.1元/G,就是提升了10万倍

微信挨骂,大头是数据,动辄几十G,文件重复存还时不时已过期
应用基本在1G之内,80M的视频库完全可以接受。

1 个赞

数据重复和库重复没有本质区别。一个涉及到视频的工具可能依赖多个第三方视频项目,每个项目又都有一个ffmpeg。最终的结果可能就是这个工具带了十个ffmpeg。