前言
许多Linux初学者装上属于他的第一个Linux后,映入眼帘的是一个黑白的命令行和乱七八糟的不认识的文件夹,这对于一个初学者来说可能相当费解。但这些看似杂乱的文件夹实则包含了Linux最底层的哲学,在这篇文章中,我们将对Linux系统的文件结构进行解析。
Linux的核心理念
“一切皆文件”
这是Linux的核心理念,在深入到具体目录之前,我们需要理解这个最为重要的设计理念
你的键盘,鼠标,或是其他的硬件设备,在Linux里被表示为文件;
Linux的系统进程信息,在Linux里被表示为文件;
一般的文件,目录,更是也被表示为文件;
这种统一的“抽象”可以让Linux用相同的工具与命令去处理几乎一切事情,这是一种伟大的操作哲学。
FHS结构
让我们来看一段目录
/
├── bin -> usr/bin
├── boot
├── dev
├── etc
├── home
│ └── 用户目录
├── lib -> usr/lib
├── media
├──mnt
├── opt
├── proc
├── root
├── run
├── sbin -> usr/bin
├── srv
├── sys
├── tmp
├── usr
│ ├── bin
│ ├── lib
│ └── local
└── var很明显,这是Linux的目录结构,无论你用的是Ubuntu、Debian、RHEL,只要是Linux的发行版,他们的结构都是如此统一。聪明的你一定发现了,他们的目录一定遵循着某种规则,而这个规则就是
FHS(Filesystem Hierarchy Standard)
这是由Linux基金会维护的一项标准,旨在规范Unix和类Unix操作系统中文件系统的结构和目录用途。这一标准定义了系统中各个目录的预期用途,有助于提高系统的可移植性、一致性和可维护性,他要求所有的Linux发行版遵循这个标准。
所以基本上可以这样说
FHS标准就是Linux目录结构标准
这意味着只要你学会了一个系统,例如Ubuntu的文件系统知识,你在其他Linux发行版上也适用,FHS规定了哪些目录应该存在,每个目录应该存放什么类型的文件。
FHS的强制性原则有:
静态与动态文件分离
可共享与不可共享分离
关于这两条原则,我们接下来再说,首先,让我们聊聊一切的开始
/(根目录)
就像人类站在地球生物链的顶点一样,根目录(/)是Linux系统中所有文件和目录的起点,是正个文件系统的顶点。
与Windows不同,Linux采用单一统一的结构,没有盘符,所有硬盘、外部驱动器、分区、最后都会返回会根目录。
他是如此的重要,所以他被设计的很精简。只包含启动、恢复和修复系统锁必备的核心内容。
他就像树干,而所有其他文件和目录,你可以理解为从树干上延伸出去的树枝与果实。
/bin
我们都知道,Linux的基本操作方式就是靠命令行,你敲下的每一个命令,你是否会好奇,系统是怎么知道这个命令是做什么的?/bin 目录可以告诉你这个答案
/bin目录存放了所有用户(包括root)所需要的基础命令
包括我们大家熟悉的 ls cp mv cat echo 等等。我们在文章的开头说道,Linux的一切都是文件,当然命令也不例外,命令作为二进制文件被存储在/bin目录下,每个命令本身都有他的归属,也就是 /bin
在如今的现代发行版中,/bin 目录通常是指向另一个目录:/usr/bin 的符号链接
也就是说,现在的 /bin 可以说是 /usr/bin 的“快捷方式“,这是因为在传统的Linux发行版中,/bin 的内容和 /usr/bin 有所重叠,维护两个目录的同步十分的麻烦,并且不理解的人经常会困惑“放在哪里”,所以现代的Linux发行版中,将两者进行了统一。
另外,如果你使用Linux安装过软件,你一定知道,假设你需要使用docker(容器软件)进行拉取镜像,当你在安装docker之前,你是无法使用 docker pull 这个命令的,但是当你使用安装工具安装了docker之后,则可以使用。那么安装docker时,docker的命令就被下载进 /usr/bin 了吗?
答案是:是的,docker命令的确被安装到了/usr/bin 下
docker的命令作为一个二进制文件被存储进/usr/bin,而 pull ps 等子命令也包含在内。
也就是说当你安装绝大部分软件时,他的命令都会被存储进/usr/bin。
当然你在bin里也可以看到,因为他们本质上是同一个东西。
/sbin
如同/bin一样,/sbin也是一个存储命令的目录,但是它储存的则是面向系统管理员的命令,普通用户通常没有权限直接执行,或者说执行了也没用
包括我们大家熟悉的fdisk, mkfs, ifconfig, reboot, shutdown 等
如同/bin一样,在现代发行版中,/sbin也是指向/usr/sbin的软链接。
值得一提的是,大部分Linux发行版中都有sudo这个命令,它的作用是让普通用户可以执行管理员的提权命令,经常有朋友会误解,认为sudo是存放在/sbin目录下的,但是实际上,sudo是存放在/bin目录下的,这样才能被普通用户所使用。
/etc
在FHS结构的部分,我们曾提到过,Linux的核心思想之一是静动态分离,把静态文件和动态文件分开存储,这样有利于管理和维护,而/etc目录,就是最重要的一个静态目录, 它存放着几乎所有系统级的程序的配置文件
etc 这个名字来源于“et cetera”(拉丁语“以及其他”的意思),在Unix早期,这个目录被用来存储其他杂项文件,但随着时间的推移,这个最杂的目录反而变成了系统配置文件的唯一标准存放位置
etc目录下的东西往往有以下四点特征:
1.文件是静态的:通常不频繁变化
2.常为文本格式:绝大部分为文本文件,可以直接用cat vim nano编辑
3.需要root权限:如此重要的目录,普通用户无权操作,只能读不能写
4.修改影响全局:一旦你对目录下的文件进行修改,这样的修改往往是全局性的
说了这么多,具体的系统配置文件都是什么呢?我们来看一段目录
当你输入
ls /etc | head -20你大概会看到如下内容:
adduser.conf
alternatives/
apt/
bash.bashrc
bash_completion/
crontab
default/
docker/
environment
fstab
group
hostname
hosts
init.d/
issue
kernel/
locale.gen
login.defs
logrotate.conf
manpath.config
...我们举个例子,用户和权限的部分
group定义了系统上的用户组信息,格式往往如此:docker:x:999:alice,bob,组密码字段通常是 x,表示密码存储在 /etc/gshadow
login.defs定义了用户账户的默认行为和限制,例如PASS_MAX_DAYS 90(密码最长使用90天)、UID_MIN 1000(普通用户UID从1000开始)、CREATE_HOME yes(默认创建家目录)、影响命令:useradd、passwd 等
很显而易见吧!
再打个比方,当你想要给你的Linux配置网络时,你该去哪呢,聪明的你一定知道网络配置这种文件大部分是静态的,所以它也应该被存储在etc目录中,所以当你需要修改网络配置时,你只需要进入etc中就可以找到网络配置文件了,但是绝大部分Linux发行版的网络配置文件位置不同,这里就不细讲了。
接下来我将用一张表解释一下我上面这个etc目录的对应内容
快速总结表
当然,每个人的目录是不一样的,所以我的这张表只是作为一个参考为了让你了解etc下到底有什么,不用硬记。
/var
聊完了静态的/etc目录,让我们来聊聊动态的目录,在/var目录下,存放着动态的数据。
这里存放着各种日志、临时文件、缓存、状态数据
如果你是一名服务器运维,你肯定没少和/var打交道。尤其是/var/log/,这个目录相当的重要,里面存放着所有系统的日志,如果你不知道你的系统和软件哪里出了问题,来这里找找肯定没错。
除了log之外,还有
/var/spool/ —— 打印队列、邮件队列等
/var/tmp/ —— 临时文件(重启后不会自动清理,区别于 /tmp)
/var/cache/ —— 应用程序缓存
/var/lib/ —— 数据库、包管理器的状态数据
等等
/tmp
这里存放临时文件。任何用户都可以读写,但只能删除自己的文件。系统重启后,/tmp 中的内容通常会被清空。
大部分现代 Linux 中,/tmp 经常被挂载为 tmpfs(内存文件系统),速度极快但重启即失
重启即失?听起来很耳熟对吧,听起来就像内存一样,又被你给想对了。
在现代Linux系统中,/tmp的内容确实是被存储在内存上的
这样证明了为什么这个目录下的东西重启就消失了,毕竟内存的特性便是断电就清空,这也符合“临时文件”的定位,在var目录中我们曾提到一个叫/var/tmp/ 的目录,他下面也存储着临时文件,它们有什么区别呢?难道和/bin与/usr/bin一样是软链接吗?
答案则是/var/tmp/ 是区别于/tmp的两个不同目录,前者是储存在硬盘上,是需要跨重启的临时文件目录,而后者则是不需要跨重启的、存储在内存上的文件目录
那么,tmp里的文件永远都在内存上吗?
答案是大部分时间是的,不过,在你安装Linux时一定见过一个叫swap的东西,这是一个Linux的机制,当你的物理内存不够用时,内核会把tmpfs的一部分不常用的内容暂时移动到硬盘上的交换分区,也就是swap中,这样可以保证你最常用的文件保持极高的读写速度。
/lib
如同/bin一样,/lib在现代Linux发行版中,实际上经常也是一个软链接,链接到/usr/lib/,他存储了Linux运行所需的库文件和内核模块,其中最主要的内容是共享库文件
我们之前提到Linux的文件与目录分为可共享和不可共享,很明显,/lib目录是一个可共享的目录。
如果你使用过Windows操作系统(我想应该没有人没使用过),那么你一定对DLL文件不陌生,事实上,他和Linux的共享库文件(后缀为.so),在概念上就是完全一样的东西,只是有一些细节上的差异。
除了.so库文件,lib目录下还存储着一个重要的东西——内核模块
这些文件被存放在/lib/modules/ 子目录下,文件名以.ko结尾(内核对象)
它们是驱动程序,在需要时动态加载,能对各类硬件产生支持,例如,当你在电脑上插入一个鼠标,系统就会在这个目录下寻找对应的.ko文件加载它。
另外,为了支持多架构并存,大部分Linux发行版中都存在/lib32,/lib64这种不同的目录来分别存放不同架构的库文件。
/usr
这是Linux最大的目录之一,如果听名字,你可能以为这是用户目录,误解为“user”,但实际上,这个目录的真正意思是
“Unix System Resources”
/usr存放只读的、可共享的用户数据,简单来说,就是那些系统正常运行所必须但不是核心的部分(最简救援模式下所必须的部分)。
这也解释了我们在之前解释的为什么/bin软链接到/usr/bin中了,例如像vim这种命令,所有用户都需要,但是其实离开了vim,Linux也可以照常运行
这同时也解释了我们在之前解释的为什么/lib软链接到/usr/lib中了,因为/lib中的文件就是需要所有用户共享的。
这个目录下还存放了管理员手动编译的软件,通常放在/usr/local/中;
以及与架构无关的共享数据,例如字体,文档,图标等,存放在/usr/share/ 中
如果你熟悉C/C++,那你你一定知道头文件,这些头文件在Linux中也有一个固定的位置,也就是/usr/include/ 。
/home
最好理解的一个目录,也叫家目录,在Linux中,每个用户都会有一个属于自己的个人目录,目录名即是用户名,里面存放了该用户的文档,下载内容,桌面,个人配置。
/root
这是root用户,也就是超级管理员的家目录,不同于普通用户的目录在/home下,root用户的的家目录是在根目录下独立的一个目录,这是出于安全考虑:即使/home 分区出现问题,root用户依旧可以正常进入自己的环境进行作业。
一般来说普通用户无权访问root目录(权限700)
/boot
这是一个极为特殊的目录,如果你足够细心,在安装Linux时的硬盘选择界面,你会发现,其中需要给boot单独划分一片区域(大小通常在1GB左右),这是因为boot目录下存放着Linux的启动文件。
之前我们提到Linux的一切皆文件,而在这里我要讲一个特殊的存在——内核
他不完全遵循这个原则,凌驾于文件系统之上:内核(Kernel)是操作系统最基本、最核心的部分。它是计算机上最先被加载到内存的程序,负责管理系统的一切——硬件、内存、进程、文件系统、网络等。
而内核就被放在boot目录下,为什么说内核凌驾于文件系统之上呢,因为内核运行之前,文件系统根本不存在!文件系统是被内核创造的
当它在开机时被加载之后,他就不再是一个文件了。他在内存中加载,负责和底层的硬件对话
这是由计算机的启动过程决定的
开机 → BIOS/UEFI → 引导程序(GRUB) → 加载内核到内存 → 内核开始运行 → 内核再挂载根文件系统
而这个引导程序(GRUB),他也被放在boot目录下,引导文件懂得读取硬盘上的文件系统,在里面寻找到/boot,之后再在/boot里去寻找内核,把他复制到内存中
但实际上引导程序并不放在/boot里,所以我们在这里并不多讲。
除了内核以外,/boot里还存放着内核配置文件、初始内存盘、内核符号表等启动时必要的文件。
由此可见/boot是多么的重要
/dev
在一切皆文件的哲学下,硬件当然也被存储为文件,所有硬件设备在这里都有对应的文件
这个目录下的每一个文件,都代表一个内核可以识别的硬件,你可以像操作普通文件一样(使用 open, read, write)来操作这些设备文件,内核会负责将这些操作翻译成对应设备的驱动程序指令。
举一个最经典的例子:硬盘
如果硬盘被存储为文件,那么向这个文件写入内容,是不是就是向硬盘写入内容呢?
答案是:是的,这些文件不是普通意义上的“文件”,它们不占用磁盘空间,而是由内核动态创建的访问入口,也被称为设备节点
你向/dev/sda 这个文件写入数据,就是向硬盘写入数据;
你向/dev/dsp这个文件写入数据,声卡就会发出声音;
这个目录完美的体现了一切皆文件的哲学!而且在这个目录下,有很多关键的设备文件,会经常用到
下面的表列出了一些常用设备文件和其常见用途。
关于磁盘命名
这部分也是经常会用到的知识,在Linux中,
SATA / SAS / USB 磁盘:命名格式为 /dev/sd[a-z]
例如
/dev/sda指的是第一块物理硬盘,/dev/sdb指的是第二块物理硬盘。
/dev/sda1指的是第一块物理硬盘的第一个分区,/dev/sda2指的是第一块物理硬盘的第二个分区。
而高速固态硬盘NVMe:命名格式则为 /dev/nvme[0-9]n[0-9]
例如
/dev/nvme0n1指的是第一块 NVMe 硬盘,/dev/nvme0n1p1指的是第一块 NVMe 硬盘的第一个分区。
好奇的你可能会问,这些硬件文件是谁创造的?难道我每次用一个新U盘还要去创建一个硬件文件?
不是, 在现代 Linux 系统中,这一切都由 udev 负责。
打个比方,当你插入一个 U 盘时,内核会通知 udev,udev 随即在 /dev 下创建 /dev/sdc 并设置好权限。拔出 U 盘时,udev 会自动删除这个文件。
/proc
依旧一切皆文件,进程和状态也不例外,/proc 就是内核和进程的实时信息窗口。
/proc是一个虚拟文件系统,它不占用硬盘空间,等等,不占用硬盘?那么他的文件里的内容是怎么来的?
答案是动态生成
当你读取一个文件时,内核会实时生成文件内容,也就是说每次都是现问现答。
在/proc 下,每一个进程都有自己的子目录,也就是/proc/[PID]/
已挂载文件系统、支持的文件系统类型,被存储为/proc/mounts, /proc/filesystems ,
CPU、内存、内核版本等系统级信息,也会有自己的目录,存放在/proc/cpuinfo, /proc/meminfo 等
让我们想想,进程,CPU实时数据这些,都是每次重启需要重新生成的内容,这和/tmp有些相似,所以/proc 也在内存里面吗?
没错,但是/proc是纯虚拟的,他不会占用内存任何空间,他只是一个信息窗口,即使 你用cat /proc/cpuinfo 输出几KB的内容,那也不是"从文件里读出来的",而是内核临时生成的。
/sys
/sys也是虚拟文件系统,他和/proc的许多特质完全一样,例如不占用存储空间,里面的内容都是内核实时生成的。
但如果只是差不多的话,内核开发者就不会费劲再创造一个 /sys 了
在Linux的初期,/proc 的功能只有一个,也就是存放进程信息/proc/[PID]/ ,但后来大家觉得这个目录实在是方便,就在滥用这个目录,往里面塞各种东西:CPU、内存、网络、内核参数...,这个目录变成了一个大杂烩,缺乏统一规范。
直到2005年,内核开发者决定重新设计一个干净的结构化的接口,专门用来暴露设备、驱动、总线、内核对象,采用树状结构,一个对象一个目录,属性就是文件,sysfs就诞生了。
相比于proc,他是结构化的,精心设计的。
其中最重要的子目录,莫过于/sys/devices/ ,他是核心,所有真实设备的树状结构,其他目录(如 class/、bus/)里的内容,本质上都是指向 /sys/devices/ 的软链接
示例:
ls /sys/devices/
# 输出类似:
# pci0000:00/ (PCI 总线)
# system/ (系统设备)
# virtual/ (虚拟设备)以网卡举例子,我们现在要在/sys/devices/ 里面找到你的网卡。
进入 PCI 设备目录
ls /sys/devices/pci0000:00/0000:00:03.0/net/
# eth0/另外一个比较重要的目录是/sys/class/ ,这是最常用的目录。它按设备的功能进行分类,而不是按物理连接。
例如,/sys/class/net 下是网络接口,/sys/class/input 下则是输入设备(键盘、鼠标),这样的分类让一切井然有序。
接下来这个表格可以告诉你常用的子目录及其功能,可以作为学习的参考。
/opt
/opt 是 Linux 文件系统中一个很有特色的目录,它的名字来源于 "Optional"(可选的)
所以,/opt是用来存放那些自带的,但是是可选项的预编译包,第三方的软件包的地方
根据FHS的规定,/opt:用于安装可选的、附加的软件包。每个软件包应该安装在自己的子目录下,比如 /opt/package/
我们在之前提到过一个目录,/usr/local ,两者都用来装"非系统默认"的软件,但分工不同,/usr/local:用于本地系统管理员手动安装的软件,通常是从源码编译的。
打个比方,你是一个帮别人装系统的电脑城员工,微信基本上是每台电脑必装的软件,所以我们把微信的安装包放在一个U盘里,如果客户需要你装上微信,你就从U盘里直接拿出微信的安装包进行安装,这个U盘就是/opt
当你要卸载软件的时候也很简单,只需要把软件所在的整个目录删除掉就好。
/mnt & /media
这两个目录都是挂载点,所以我放在一起讲
首先我们需要知道什么是挂载
在Windows中,每个设备都有自己的根,也就是C: D: 这样的盘符,但Linux不一样,之前我们说过,Linux采用单一的统一的文件系统,挂载就是把你的存储设备(或分区)插入到Linux这个统一的文件系统中(目录树的某个位置),让资源管理器可以直接看到。
虽然如此,但是他们有本质上的区别,
/mnt 是一个空目录,专门用来给系统管理员临时挂载文件系统。也就是手动挂载点
在管理员需要的时候,例如当系统无法启动时,用 USB 启动
这个目录的特点是需要手动挂载,自己执行 mount 命令,通常只是临时用一下,用完就 umount ,而因为只有一个目录,通常这个目录下只能挂载一个设备。
而/media则是自动挂载点,
插上设备就会自动挂载,可以同时插入多个 U 盘,各自有独立目录,不需要知道 mount 命令,通常挂载到 /media/用户名/ 下,只有该用户有权限。
/srv
我们都知道,Linux最常见的场景是作为服务器,因为他轻量,低功耗。
而/srv 就是用来存放本系统所提供的服务(如网站、FTP、版本控制仓库)的数据文件的地方。
所以在个人电脑上往往用不到这个目录。
根据FHS的规定,/srv包含本系统所提供的特定服务的数据。服务的数据(如网站页面、FTP 文件、版本控制仓库)应该放在/sr下的子目录中,子目录的名称由服务管理定。主要目的是让用户可以找到服务的数据位置,从而方便备份、迁移理。
举一个最常见的例子,Web服务器
/srv/www/
├── example.com/
│ ├── index.html
│ ├── css/
│ └── js/
└── blog.example.com/
├── index.php
└── wp-content/虽然 FHS 建议使用 /srv,但很多流行的服务并没有遵循这个标准,我们这里就不细说了,你只需要知道,这个目录下是用来存放服务器的服务端软件即可。
结语
Linux文件系统结构看似杂乱无章,但其实全部有迹可循,FHS 标准保证了不同发行版之间的一致性。理解这些目录的意义,能让你更高效地使用 Linux。
本文AI含量为0%
首发于 焰白小站 enento.com
本文采用 CC BY-NC 4.0 许可协议,转载请注明出处。
Linux基础教程之文件系统结构详解
http://enento.cloud/archives/jiaoxuelinuxFHS
评论