Linux文件目录结构详解

1. FHS是什么?

Filesystem Hierarchy Standard(文件系统层次化标准)的缩写,多数Linux版本采用这种文件组织形式,类似于Windows操作系统中c盘的文件目录,FHS采用树形结构组织文件。FHS定义了系统中每个区域的用途、所需要的最小构成的文件和目录,同时还给出了例外处理与矛盾处理。

通俗的讲就是解决哪些鸡蛋应该放在哪些篮子的问题.

2. 为什么要有FHS?

因为基于Linux开发新的产品或distributions的社群、公司以及个人实在是太多啦。如果每个人都用自己的想法来定义目录结构,那么将可能造成很多文件管理上的困扰。你可以闭上眼睛想象一下,你刚刚进入一家企业后,所接触到的Linux目录以及配置方法尽然和你以前所学习到的完全不一样,很难在继续想了吧(花了好多钱以及好多时间竟然白学了)。所以后来就有所谓的Filesystem Hierarchy Standard(FHS)这个标准就风风火火的出炉啦。

根据FHS的官方文件指出,他们的主要目的是希望让使用者可以了解到已安装的软件通常存放在哪个目录下,所以他们希望独立的软件开发商,操作系统制造者,以及想要维护系统的用户(系统管理员),都能够遵循FHS的标准,也就是说,FHS的重点在于规范每个特定的目录下应该要存放什么样子的数据而已。这样做的好处非常多,因为Linux操作系统就能够在既有的面貌下(目录架构不变)发展出开发者想要的独特风格。

事实上,FHS是根据过去的经验总结出来的, 而且一直在持续的改版,FHS依据文件系统使用的频率与否允许使用者是否随意改动,而将目录定义成为4种交互作用的形态。

3. FHS目录的架构都有些啥?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
├── lib -> usr/lib
├── lib32 -> usr/lib32
├── lib64 -> usr/lib64
├── libx32 -> usr/libx32
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/sbin
├── srv
├── sys
├── tmp
├── usr
├── bin
├── include
├── lib
├── lib32
├── lib64
├── libexec
├── libx32
├── local
├── sbin
├── share
└── src
└── var
├── cache
├── lib
├── local
├── lock -> /run/lock
├── log
├── mail
├── opt
├── run -> /run
├── spool
└── tmp

4. 详解之前

在进入详解之前, 我们来思考一个问题, 这个问题对我们理解目录结构将会非常有帮助.

4.1. 程序是由什么构成的?

一个完整的程序或软件通常由以下四部分组成,

  1. 可执行文件.
    这些文件一般是可执行的二进制文件(binary), 当然也有例外, 比如shell脚本, 它也是可执行的文件, 这些统称可执行文件.
    它有个显著的特点就是就是它有不可变性, 当然这里的不可变性是相对的, 不是绝对的. 什么含义? 就是软件一旦安装, 在它的生命周期中, 这些可执行文件几乎是不怎么改变的, 直到升级到新的版本, 或者被卸载. 正因为它有不变性, 我们在备份的时候, 可以不考虑可执行程序, 或者以较低的频率备份可执行文件. 因为他们能够很容易的被重建起来.
    另外正因为它们有不可变性, 使得他们有较高的共享价值, 即可以在一台机器上只安装一份可执行程序, 所有用户共享一份可执行程序. 甚至我们可以在一个网络中只安装一份可执行程序, 整个网络中共享一份可执行程序. 例如我们可以在NFS服务器上保存可执行程序, 其他主机通过NFS远程挂载的方式挂载到本地主机, 这样我们不必每个主机逐一安装同一软件.
    另外它的特点是可执行的, 这也是它区别与其它类型文件的显著区别. 什么含义? 即它是可以独立加载进内存, 被CPU执行的. 正因为它有这个特点, 我们要特别小心这些可执行文件, 要防止它们被病毒感染或被恶意程序篡改. 所以针对这类程序的我们进行病毒查杀的频率要高.
  2. 库文件
    程序执行时依赖的一些动态或静态类库, 如一些dll文件. 有时多应用程序可能共享同一份类库. 一些基础类库可能会被很多的软件所依赖. 有时同一家公司的产品可能会共用一份库文件. 有时一份软件有它特有的依赖库. 这类文件, 我们在删除的时候一定要非常小心, 因为意外删除可能导致多款软件运转失灵. 安装时也可能因为新版本覆盖旧版本导致,其它软件出现兼容性问题. 所以我们在进行复杂的升级, 安装前要记得备份这些库文件. 所以这类文件备份频率要高于可执行文件, 以便当系统崩溃时从备份中恢复.
    另外, 虽然它们不是直接可执行的文件, 但是它们也会被可执行程序, 或系统调用加载到内存被CPU执行, 也需要频繁地进行病毒查杀.
  3. 配置文件
    这类文件通常是文本文件, 例如apache的配置, tomcat的配置. 这类文件通常不具有可共享性, 每个系统之所以会表现出不同的特性, 通常是有配置文件决定的. 不同主机, 用户都有不同的配置文件. 他们具有可变性和不可共享性.
  4. 数据
    数据是一个企业或最重要的资产, 通常情况下数据会随着业务的发展逐渐增长. 这类数据具有高可变性. 所以对备份要求较高, 有些需要定期备份甚至实时备份. 当然数据也分为很多种类, 对于数据种类的研究可以另开一篇专题了, 比如日志类型的数据, 要定期归档, 清理.
  5. 帮助文档
    帮助文档具有高不可变性和高共享性. 其不可变性, 并不代表文档不会更新, 而是指针对特定版本的应用程序, 其帮助文档内容是相当不变化的.

4.2. 软件如何分类?

从系统管理的角度, 软件可以分为系统软件和应用软件.
系统软件一般是支撑整个系统运行的必要软件, 比如磁盘管理工具, 网络工具, shell等. 用于构成整个计算机的infrastrure 或用于维护, 如果以使用者角色划分的话, 他们是系统管理员经常使用的软件.
应用软件是指运行在系统之上特供特定功能的软件, 比如办公软件, 音频视频播放软件等. 以使用者角色划分的话, 他们是用户经常使用的软件.
这里为什么要谈论软件分类, 因为我们在规划目录结构时, 尤其在企业应用中, 管理员角色和用户人群是分开的, 所以要考虑将系统管理员使用的软件与用户使用到的软件及配置要分割开来. 保证应用软件的运行不会导致整个系统的崩溃.

5. 目录详解

/ 根目录
根目录的意思与内容根目录是整个系统最重要的一个目录,因为不但所有的目录都是由根目录衍生出来的。同时根目录也是开机、关闭、系统修复等功能有关的。由于系统开机时需要特定的开机软件,核心文件,开机程序所需的程序,函数库等文件数据。因为根目录很重要,所以在FHS要求方面,它希望根目录不要放在非常大的分区上面,因为越大的分区,你会存储更多的数据,如此一来根目录所在的分区就可能会有较大的发生错误的机会, 一旦根分区发生错误就会导致系统崩溃。依据FHS的建议:根目录所在的分区越小越好,且应用程序所安装的软件最好不要与根目录放在一个分区中,保持根目录越小越好。

/bin: binary(二进制) 的简写, 存放用户和系统都可以访问的可执行文件.

/usr
/usr的意义与内容依据FHS的基本定义,/usr里面存放的数据属于可分享的与不可变动的(shareable、static),如果你知道如何通过网络进行分区的挂载(例如:NFS服务器),那么/usr确实可以分享给全局网络内的其他主机来用啦。很多人都误会/usr为user的缩写,其实usr是Unix software Resourece的缩写,也就是Unix操作系统软件资源所存放的目录。FHS建议所有软件开发者,将他们的可执行文件合理地分类存放到这个目录的子目录下,而不是自行独立创建一级目录。因为所有系统默认的软件(distributions发布者提供的软件)都会放到/usr目录下。就像我们windows系统下的windows文件夹和program files文件夹这两个文件夹的结合体。这个目录占用最多的磁盘空间。
而用户安装的非系统程序和其他东西建议存放在/usr/local 下.这样可能在升级新版系统或新distribution时无须重新安装全部程序.

/usr/X11R6
X Window系统的所有文件.为简化X的开发和安装,X Window的文件没有集成到系统中. X自己在/usr/X11R6 下类似/usr .

/usr/X386
类似/usr/X11R6 ,但是给X11 Release 5的.

/usr/bin
几乎所有用户命令.有些命令在/bin 或/usr/local/bin 中.

/usr/sbin
根文件系统必要的系统管理命令,例如多数服务程序.

/usr/man , /usr/info , /usr/doc
手册页、GNU信息文档和各种其他文档文件.

/usr/include
C编程语言的头文件.为了一致性这实际上应该在/usr/lib 下,但传统上支持这个名字.

/usr/lib
程序或子系统的不变的数据文件,包括一些site-wide配置文件.名字lib来源于库(library); 编程的原始库存在/usr/lib 里.

/usr/local
本地安装的软件和其他文件放在这里. 用户自己编译的软件默认会安装到这个目录下。这里主要存放那些手动安装的软件,即不是通过“新立得”或apt-get安装的软件。它和/usr目录具有相类似的目录结构。让软件包管理器来管理/usr目录,而把自定义的脚本(scripts)放到/usr/local目录下面

/var文件系统
var是variable的简写形式(可变的). 是运行时会占用比较大的硬盘容量的目录,那么/var就是在系统运行后才会渐渐占用磁盘容量的目录。因为/var目录主要针对经常变动的文件,包括缓存(cache)、登录文件(log file)以及某些软件运行所产生的文件。包括程序文件(log file、run file)。如mysql数据库的文件等。

/var 包括系统一般运行时要改变的数据,具有不可共享性. 每个系统是特定的,即不通过网络与其他计算机共享.

/var/catman
当要求格式化时的man页的cache.man页的源文件一般存在/usr/man/man中;有些man页可能有预格式化的版本,存在/usr/man/cat 中.而其他的man页在第一次看时需要格式化,格式化完的版本存在/var/man 中,这样其他人再看相同的页时就无须等待格式化了. (/var/catman 经常被清除,就象清除临时目录一样.)

/var/lib
系统正常运行时要改变的库文件.

/var/local
/usr/local 中安装的程序的可变数据(即系统管理员安装的程序).注意,如果必要,即使本地安装的程序也会使用其他/var 目录,例如/var/lock .

/var/lock
锁定文件.许多程序遵循在/var/lock 中产生一个锁定文件的约定,以支持他们正在使用某个特定的设备或文件.其他程序注意到这个锁定文件,将不试图使用这个设备或文件.

/var/log
各种程序的Log文件,特别是login (/var/log/wtmp log所有到系统的登录和注销) 和syslog (/var/log/messages 里存储所有核心和系统程序信息. /var/log 里的文件经常不确定地增长,应该定期清除.

/var/run
保存到下次引导前有效的关于系统的信息文件.例如, /var/run/utmp 包含当前登录的用户的信息.

/var/spool
mail, news, 打印队列和其他队列工作的目录.每个不同的spool在/var/spool 下有自己的子目录,例如,用户的邮箱在/var/spool/mail 中.

/var/tmp
比/tmp 允许的大或需要存在较长时间的临时文件. (虽然系统管理员可能不允许/var/tmp 有很旧的文件.)

/opt:用户级的程序目录
这里主要存放那些可选的程序, 在新版的FHS中, 建议使用/usr/local替代, 其一是opt是一个一级目录, 在新版的FHS中, 目录越来越层次化, 其而local的意义更能代表这类软件的意义。你想尝试最新的firefox测试版吗?那就装到/opt目录下吧,这样,当你尝试完,想删掉firefox的时候,你就可 以直接删除它,而不影响系统其他任何设置。安装到/opt目录下的程序,它所有的数据、库文件等等都是放在同个目录下面。
举个例子:刚才装的测试版firefox,就可以装到/opt/firefox_beta目录下,/opt/firefox_beta目录下面就包含了运 行firefox所需要的所有文件、库、数据等等。要删除firefox的时候,你只需删除/opt/firefox_beta目录即可,非常简单。
在硬盘容量不够时,也可将/opt单独挂载到其他磁盘上使用。

/media  一些可以热拔插的介质(如CD-ROMs)的挂载点 (在FHS-2.3中出现).

/mnt   临时挂载的文件系统

/dev: 设备文件. device(设备)的简写.

/etc: 主要用于存放配置文件.

/home: 用户的主目录. 可以存放用户级别的配置文件, 数据等. 比如bash的配置文件, maven, gradle等等的用户配置文件

/root: root用户的主目录, root用户主目录为何单独拥有一个一级目录,而且主目录往往挂载在一个单独的硬盘分区, 一来是为了确保更高的安全性. 另外是root用来救援其它用户的, 当其它其用户挂掉的时候, root是不能挂掉的.

/proc: process进程的简写. 将进程和内核信息以文件形式呈现的虚拟文件系统。在Linux中,与procfs mount(进程文件系统)对应.

/run: 运行时变量数据:从本次启动到现在的系统信息。如当前登陆的用户和正在运行的守护进程

/srv    本系统提供的特定站点的数据。如web服务器提供的数据和脚本,FTP服务器提供的数据,VCS的仓库

/sys    包含连接到本台计算机的设备信息

/tmp   临时文件(和/var/tmp相同). 通常在重启后清空,并且受到严格的大小限制

6. FHS 约定

大多数Linux发行版遵循文件系统层次结构标准(FHS),并且为保持FHS约定发布了相关政策。GoboLinux 和 NixOS 提供了有意不遵循FHS约定的实现
有些基本遵循这个标准的发行版在部分方面有些违背,如

  • 现代Linux发行版将/sys 作为可以被连接到此系统的设备修改和保存的虚拟文件系统(sysfs,相当于/proc),但是许多UNIX和类UNIX系统使用/sys 作为指向 kernel source tree 的符号连接
  • 许多现代UNIX系统(像FreeBSD ,通过它的端口系统)安装第三方包至/usr/local 然而却将本应是操作系统的代码放在/usr 中
  • 一些Linux发行版不再区分/lib 与/usr/lib,并且将lib 作为指向 /usr/lib 的软连接
  • 一些Linux发行版不再区分 /bin 与 /usr/bin 和/sbin 与/usr/sbin 。他们将 /bin 作为指向 /usr/bin 的软连接, 将/sbin 作为指向/usr/sbin 的软连接

现代Linux发行版将/run 作为(遵循FHS3.0的)保存不稳定的运行时数据的临时文件系统(tmpfs)。根据FHS2.3,这类数据被保存在/var/run ,但是由于在启动时这个目录并不总是可用,会导致一些问题。所以,这些程序必须借助欺骗的方式,如使用类似 /dev/.udev, /dev/.mdadm, /dev/.systemd 或 /dev/.mount 等并不是用来保存这些数据的设备目录。除其他好处外,这样也会使根目录以只读方式挂载的系统更容易使用。例如,以下是Debian在2013年的Wheezy版本中作出的改变:

1
2
3
4
5
6
7
8
/dev/.* → /run/*
/dev/shm → /run/shm
/dev/shm/* → /run/*
/etc/* (writeable files) → /run/*
/lib/init/rw → /run
/var/lock → /run/lock
/var/run → /run
/tmp → /run/tmp

7. FHS的发展历史

当FHS被以FSSTND (Filesystem Standard的缩写)被创建时,其他UNIX和类UNIX系统已经有了他们自己的标准。比较典型的例子有 自从 Version 7 Unix (in 1979)发布以来就存在的the hier(7) description of file system layout; the SunOS filesystem(7) 和它的后继 the Solaris filesystem(5)

7.1. 历史版本

legendVersionRelease DateNotes
旧版本11994/2/14FSSTND
旧版本1.11994/10/9FSSTND
旧版本1.21995/3/28FSSTND
旧版本21997/10/26FHS 2.0 直接继承自FSSTND 1.2 。 FSSTND更名为FHS
旧版本2.12000/4/12FHS
旧版本2.22001/5/23FHS
仍支持2.32004/1/29FHS
最新版32015/5/18FHS

8. 一些疑问

8.1. linux下/bin和/usr/bin和/usr/local/bin的区别?

/bin 是所有用户都可以访问并执行的可执行程序。包括超级用户及一般用户。
/usr/bin 是系统安装时自带的一些可执行程序。即系统程序,轻易不要去动里面的东西,容易入坑。
/usr/local/bin 是用户自行编译安装时默认的可执行程序的安装位置,这个不小心误删点什么,不会影响大局。

9. 后续

更多linux相关知识, 请参考鹏叔的技术博客linux tag, 获取实时更新的Linux文章.

10. 参考文档

linux中的/usr,/var,/opt目录详解

文件系统层次结构标准(FHS)(for Linux)

wiki Filesystem_Hierarchy_Standard

Ubuntu Hier 7

FHS 3.0

Filesystem Hierarchy Standard