我们大家应该知道,Linux 和 UNIX 中的文件系统是一个以 / 为根的树状式文件结构,/ 是 Linux 和 UNIX 中的根目录,也是整个文件系统的起点。所有的文件和目录都位于 / 路径下,包括我们经常听到的 /usr、/etc、/bin、/home 等。在早期的 UNIX 系统中,各个厂家定义的文件系统命名规则比较混乱,难以区分。
为了避免在 Linux 系统上也出现这种命名混乱的问题,在 1994 年推出了 FSSTND(FileSystem Standard)的 Linux 文件系统层次结构标准。后来 UNIX 团队将 FSSTND 发扬光大,形成了后来的 FHS(FileSystem Hierarchy Standard)。
FHS 标准使得众多的 Linux distributions(Linux 发行版)有了统一的文件系统命名标准。简单来说,FHS 就是一种文件系统的命名规范。一般来说,Linux 发行版都需要遵循 FHS 规定的目录结构、目录内容以及文件类型的权限。
FHS 主要定义了两层规范:
- 第一层是
/ 下面的各个目录应该存放什么类型的文件数据。例如,/etc 下面需要放置配置文件,/bin 和 /sbin 下面需要放置可执行文件。
- 第二层是针对
/usr 和 /var 这两个目录来定义的。例如,/usr/share 需要放置共享数据,/var/log 需要放置系统日志文件。
下面就来详细介绍一下 Linux 在 / 根目录下各个子目录的定义和规范。
FHS 规范
这里介绍的规范只是 FHS 文档指定的一部分,完整的标准可在 http://www.pathname.com/fhs/ 在线查阅。
首先介绍根目录的重要性和意义:根目录是整个系统最重要的一个目录,所有后续目录都基于根目录衍生。更重要的是,根目录与系统开机、还原和修复密切相关。由于系统开机需要特定的环境,当系统出现错误时,根目录也必须包含能够修复文件系统的程序。因此,FHS 建议不要将根目录的分区设置得过大,实际上越小越好,以减少出错概率。
FHS 同样规定了根目录下应该存在以下目录。
/home 目录
/home 目录是系统默认的用户主文件夹(home directory)。
/boot 目录
/boot 目录包含启动操作系统所需的静态文件,例如 Linux 内核。这些文件对系统的启动至关重要。常用的 Linux 内核文件名为 vmlinuz。如果你使用 grub2 作为启动引导程序,通常还会存在 /boot/grub2 这个目录。
下图展示了一个刚搭建完成的 Linux 系统中 /boot 目录下的内容。

警告:千万不要删除 /boot 目录,否则可能导致系统无法启动。
/dev 目录
/dev 目录存放设备节点,这些节点对应 Linux 系统中的物理设备或由内核提供的虚拟文件系统。这些设备节点对系统的正常运行至关重要。/dev 目录及其子目录下的设备主要分为字符设备(如鼠标、键盘、调制解调器)和块设备(如硬盘、软盘驱动器)。存储 /dev 目录下的文件就相当于在操作对应的设备。
一些比较重要的设备文件包括:
/dev/hda:主 IDE 通道上的主设备。
/dev/hdb:主 IDE 通道上的从设备。
/dev/tty0:第一个虚拟控制台。
/dev/tty1:第二个虚拟控制台。
/dev/sda:主 SCSI 和 SATA 通道上的第一个设备。
/dev/lp0:第一个并行端口。
下图展示了 /dev 目录下的部分设备文件列表。

/etc 目录
/etc 目录用于存放计算机本地的配置文件。系统主要的配置文件(如账号密码、服务的启停配置)都放在这里。通常,普通用户对此目录只有读取权限,只有 root 用户才拥有修改权限。
/etc 下一些重要的文件和目录包括:
/etc/modprobe.d:内核驱动模块配置。
/etc/passwd:存储用户账户信息。
/etc/fstab:存储文件系统挂载信息。
/etc/issue:存储系统启动时显示的信息。
需要注意的是,/etc 目录下不应存放二进制可执行文件,二进制文件最好放在 /sbin 和 /bin 中。此外,还有两个重要的子目录:/etc/x11 用于存放 X Window 系统配置文件;/etc/opt 主要用于存放第三方软件 /opt 的相关配置文件。

/lib 目录
系统的函数库有很多,而 /lib 目录就像一个仓库,用于存放执行 /bin 和 /sbin 中二进制文件所必需的库文件。这些共享库映像对于系统启动和执行根文件系统中的命令至关重要。

media 是“媒体”的英文,因此 /media 目录下通常存放可移动媒体(如 USB、DVD、CD-ROM 和 Zip 磁盘)的挂载点及其子目录。
/mnt 目录
如果你想要临时挂载某些额外的设备,可以放在 /mnt 目录下。其实最早的时候,/mnt 的用途与 /media 一样,后来有了专门的 /media 目录之后,/mnt 就被更多地用于临时挂载了。
/opt 目录
/opt/ 目录为大多数第三方应用程序软件包提供存储空间。放置在 /opt/ 目录中的软件包会创建一个与包同名的子目录。这种方式将所有相关文件集中管理,便于系统管理员确定特定软件包中每个文件的角色。
例如,如果 sample 是位于 /opt/ 目录中的一个软件包,那么其所有文件都放置在 /opt/sample/ 目录结构中,比如二进制文件放在 /opt/sample/bin/,手册页放在 /opt/sample/man/。

/proc 目录
/proc 目录本身是一个虚拟文件系统(virtual filesystem),它存放的数据在内存中,包括系统核心信息、进程信息、外设及网络状态等。因为这个目录下的数据都在内存中,所以它本身不占用磁盘空间。
这个目录下比较重要的文件有 /proc/cpuinfo、/proc/dma、/proc/interrupts、/proc/net/ 等。

/sbin 目录
/sbin 目录存储供 root 用户使用的可执行文件。/sbin 中的可执行文件通常在启动时使用,用于系统管理和执行系统恢复操作。除了 /bin 中的二进制文件外,/sbin 还包含启动、恢复和修复系统所必需的二进制文件。
/sbin 目录下常见的命令有 arp、clock、halt、init、grub、ifconfig、route、shutdown 等。

/tmp 目录
这个目录下面存放的都是一些临时文件,这些文件在系统重新启动时会被清除。

/sys 目录
这个目录与 /proc 非常类似,也是一个虚拟文件系统,主要用于记录内核与系统硬件相关的信息。这个目录同样不占用磁盘空间。

/usr 目录
/usr 目录需要重点了解。很多读者误以为 /usr 是 user 的缩写,其实它是 Unix Software Resource 的缩写。FHS 建议软件开发者将数据合理地放置在这个目录的子目录下,而不是自己创建独立的目录。
所有系统默认的软件都会放在 /usr 下面。这个目录有点类似 Windows 中 C:\Windows\ 和 C:\Program files\ 这两个目录的综合体。系统刚安装完毕后,这个目录会占用较多的磁盘容量。/usr 目录建议包含以下子目录:
/usr/bin/:一般用户能够使用的命令都放在这个目录下。从 CentOS 7 开始,/usr/bin 下的命令与 /bin 目录下的命令完全相同。
/usr/lib/:功能基本上与 /lib 相同,通常 /lib 会链接到这个目录。
/usr/local:系统管理员在本机自行下载安装的软件,建议安装到这个目录下,便于集中管理。
/usr/sbin:非系统正常运行所必需的系统命令,最常见的是某些网络服务器软件的服务指令。其基本功能与 /sbin 类似,目前 /sbin 通常链接到此目录。
/usr/share:共享文件放置区。这个目录下还有 /usr/share/man(手册页)、/usr/share/doc(文档)、/usr/share/zoneinfo(时区信息)等子目录。
/usr/games:与游戏相关的数据存放处。
/usr/include:C/C++ 等程序语言的头文件(header)和包含文件(include)存放处。通常系统中的链接也指向这里。
/usr/src:一般源码建议放在这里,src 是 source 的缩写。至于内核源码则建议放在 /usr/src/linux 目录下。

/run 目录
早期的 FHS 规定系统启动后产生的各项信息应该放置到 /var/run 目录下,而新版的 FHS 则规范到 /run 目录下。
/var 目录
如果说 /usr 是在系统安装时会占用较大磁盘容量的目录,那么 /var 就是在系统运行后才会逐渐占用磁盘容量的目录。/var 主要包括缓存、日志文件以及某些软件运行所产生的文件,例如 MySQL 数据库文件等。常见的子目录有:
/var/cache:应用程序缓存目录。
/var/crash:系统错误信息存放目录。
/var/log:日志记录目录。
/var/run:进程的标识数据目录。
/var/tmp:临时文件目录。
/var/lock:文件锁定记录目录。

/srv 目录
srv 可以看作是 service 的缩写。这是一些网络服务启动后,服务所需要读取的数据目录。常见的服务如 WWW、FTP 等。
CentOS 7 在目录编排上与过去的版本有所不同,最大的差异在于将许多原本应该放在根目录下的目录,全部挪到了 /usr 里面,并进行了符号链接设置。这些变化包括:
/bin -> /usr/bin
/sbin -> /usr/sbin
/lib -> /usr/lib
/lib64 -> /usr/lib64
/var/lock -> /run/lock
/var/run -> /run
为了方便大家直观地理解这些目录的用途和关系,下图以目录树的形式进行了归纳总结。图中的目录关系很像一棵树,因此这个结构又被称为“目录树”。

绝对路径和相对路径
和许多操作系统一样,Linux 中的路径也分为绝对路径(absolute)和相对路径(relative)。这两种路径的写法依据如下:
- 由根目录开始的路径称为绝对路径,例如目录树中的
/boot、/usr/local 等。
- 相对于当前所在文件位置的路径称为相对路径,例如
../var/log。
注意:相对路径是以你当前所在路径的相对位置来计算的。
- 例如,当前在
/boot 目录,想要移动到 /usr/src 目录。
- 绝对路径写法:
/usr/src
- 相对路径写法:
../usr/src
这里还需要注意两个特殊的目录符号:
. :代表当前目录,也可以使用 ./ 来表示。
.. :代表上一层目录,也可以用 ../ 来表示。
关于绝对路径和相对路径的取舍:当文件路径很长时,推荐使用相对路径,因为不需要像绝对路径那样写出完整路径,使用 ../ 等方式更为简洁。然而,从路径的准确性和可靠性来说,绝对路径优于相对路径。
如果你是在编写程序来管理系统,务必使用绝对路径。因为绝对路径无论文件位于何处,都能准确找到指定文件;而使用相对路径时,如果文件被移动,程序就可能找不到该文件。
与目录有关的指令
下面介绍一些常用的目录操作指令。
cd
cd 是 change directory 的缩写,用于切换当前工作目录。主要有以下四种切换方式:
cd /路径名 # 表示切换到指定的工作目录
cd ./ # 表示切换到当前工作目录(无实际切换)
cd .. # 表示切换到当前工作目录的上一层目录
cd ~ # 表示返回到当前用户的主目录
演示操作如下:

可以看到,分别使用 cd /usr/local 切换到了指定目录;使用 cd ./ 没有切换任何目录;使用 cd .. 切换到了上一级目录;使用 cd ~ 切换到了当前登录用户的默认主目录。
需要注意的是,直接使用 cd 的效果与 cd ~ 相同,即 cd 等价于 cd ~。
pwd
pwd 是最常用的指令之一,使用频率几乎与 cd 相当。pwd 是 Print Working Directory 的缩写,用于打印出当前所在目录的路径。
实际上,pwd 不一定只用于显示当前工作路径,它也可以用来显示指定工作目录下的文件路径。

不过,这个用法在实践中可能用途不大,因为通常我们已经知道目标路径是什么了。
mkdir
mkdir 用于创建新目录,它是 make directory 的缩写。常用的两个参数是:
-m:直接设置新目录的权限,不考虑默认的 umask 设置。
-p:递归创建目录,即如果上级目录不存在,则一并创建。
下面是在 /tmp 目录下创建一个名为 test1 空目录的操作。

如果你想创建一个权限为 711(即所有者有全部权限,组用户和其他用户只有执行权限)的目录,可以使用以下命令:
mkdir -m 711 test2

上图中的 ls -ld 命令用于列出文件目录的详细信息,最前面显示的就是文件的权限。
如果希望快速创建多层目录结构,例如 /tmp/test1/test2/test3/test4,直接使用 mkdir 会失败:

此时就需要 -p 参数出场了,它允许我们递归创建所需的各级目录:

rmdir
rmdir 用于删除空目录。它的用法与 mkdir 类似,mkdir -p 用于递归创建目录,同样,rmdir -p 也能够递归删除空目录。如下图所示:

需要注意的是,rmdir 只能删除空目录。如果目录内有内容,则无法删除。此时可以使用 rm -r 命令来强制删除目录及其内容。
mv
mv 命令可以修改目录的名称。例如,我们创建了一个名为 test 的目录,后来想将其改为更能体现所有者意图的名字,就可以使用 mv 指令。

在了解了基本的目录操作之后,让我们思考一个问题:为什么我们能在系统的任何目录下执行 ls 命令并显示内容?按理说,ls 命令不应该只在它存放的路径下才能使用吗?
这就要涉及到环境变量 PATH 的概念。PATH 是一个环境变量,当我们在命令行执行一条指令时,系统会按照 PATH 变量的设置,依次去每个 PATH 所指向的目录中搜寻与该指令同名的可执行文件。如果找到,则执行最先找到的那个。
希望这篇关于 Linux 文件系统 FHS 标准和目录操作的详解能帮助你更深入地理解 Linux 系统的组织方式。如果你想与更多开发者交流此类计算机基础知识,欢迎来 云栈社区 探讨。