第03章 Linux文件系统与目录结构

亲爱的读者朋友,当你打开这一章的时候,你已经迈出了探索Linux世界非常关键的一步。如果说操作系统是一座宏伟的城市,那么文件系统就是这座城市的"道路规划图"和"建筑布局图"——它决定了数据如何存储、如何组织、如何被找到。对于零基础的你来说,本章内容可能听起来有些抽象,但请放心,我会用大量生活中的类比和比喻,带你一步步揭开Linux文件系统的神秘面纱。读完这一章,你将真正理解Linux的"五脏六腑",知道那些看起来很神秘的目录到底是什么意思,这将为你后续的学习打下最坚实的基础。


3.1 文件系统概念详解

3.1.1 什么是文件系统

在学习Linux之前,你可能每天都在和文件打交道——在电脑上创建Word文档、下载电影、保存照片、整理文件夹。但你有没有想过,这些文件到底是怎样被保存到硬盘里的?当你双击打开一个文件时,电脑又是如何快速找到它的?这一切的背后,都有一个叫做"文件系统"(File System)的大管家在默默工作。

让我们用一个形象的类比来理解文件系统。想象一下一座巨大的图书馆:这座图书馆有成千上万个书架,每个书架上摆满了书籍。如果没有一套完善的管理系统——没有图书分类法、没有索引卡片、没有书架编号、没有借阅记录——那么当读者想要找到某一本特定的书时,他就只能一个书架一个书架地翻找,这几乎是不可能的任务。

文件系统就扮演着这座图书馆"管理系统"的角色。具体来说,文件系统是一套用于组织、存储、检索和管理数据的软件机制。它定义了数据在存储设备(如硬盘、SSD固态硬盘、U盘等)上是如何被存储的,文件是如何被命名的,文件夹(在Linux中称为"目录")是如何被组织的,以及操作系统如何读取和写入这些数据。

当你在电脑上保存一个名为"我的照片.jpg"的文件时,文件系统会做以下几件事:

  1. 找到一个空闲的存储空间:文件系统会在硬盘上寻找没有被使用的"块"(Block),就像图书管理员在书架上寻找空位来放置新书一样。

  2. 记录文件的位置和属性:文件系统会在一个特殊的数据结构(叫做inode,我们后面会详细讲)中记录这个文件的名字、大小、创建时间、修改时间、存储位置等信息。这就像图书馆的索引卡片,上面记录了书名、作者、书架位置和借阅状态。

  3. 建立目录层次关系:文件系统会把这个文件归入某个目录下,维护好"父子关系"。比如"/home/用户名/图片/我的照片.jpg"这条路径,就表示这个文件在"图片"文件夹下,"图片"文件夹又在"用户名"文件夹下。这就像图书馆里的分类:文学类→中国小说→当代小说→某本书。

  4. 提供访问接口:当你下次想打开这个文件时,文件系统会根据你提供的路径,一层层找到对应的目录,查到文件存储在哪个硬盘块上,然后把数据读取出来交给你使用的应用程序。

没有文件系统,硬盘就是一块"裸金属",上面只有无数个点(存储单元),操作系统根本不知道该去哪里找什么数据。有了文件系统,硬盘就变成了一个有秩序、有结构、可以方便使用的存储空间。

生活中的类比加深理解

  • 文件系统 = 超市的货架管理系统:超市里有成千上万的商品,每种商品都有固定的摆放位置——蔬菜区、水果区、饮料区、日用品区。每个区又有细分货架。如果你问导购员"酱油在哪里",她能快速告诉你"在调味品区第3排货架第2层"。文件系统也是这样,当你要找一个文件时,它能快速定位到硬盘上的具体位置。

  • 文件系统 = 快递仓库的物流系统:双十一期间,快递公司每天要处理上亿件包裹。每个包裹都有一个唯一的单号,仓库按照区域、路线分拣。没有这套系统,想在堆积如山的包裹中找到你的一件,无异于大海捞针。

3.1.2 文件系统的核心功能

文件系统的核心功能可以概括为以下五个方面,每一个都非常重要:

1. 存储空间管理(Space Management)

存储设备(硬盘、SSD等)的容量是有限的。文件系统需要决定如何把文件分散或集中存放在这些物理空间上,以及如何跟踪哪些空间已被使用、哪些空间是空闲的。

可以把这理解为停车场的车位管理。停车场里有很多车位,有的停着车,有的空着。管理员需要知道每个车位的状态。当新车进来时,他要把车引导到空车位;当车开走时,他要标记这个车位为空闲。如果管理不善,可能会出现"明明有很多空位,但新来的车找不到地方停"的尴尬局面(在文件系统中叫做"碎片化"或"空间分配失败")。

文件系统使用不同的策略来管理空间:

  • 连续分配:把文件存放在连续的物理块中,就像把一整套百科全书放在相邻的几个书架上。优点是读取速度快,缺点是容易产生碎片。
  • 链式分配:文件的每个块都指向下一个块的地址,就像寻宝游戏中的线索链。优点是灵活,缺点是如果某个块损坏,后面的内容就全部丢失。
  • 索引分配:通过一个索引块记录文件所有数据块的位置,就像图书的目录页。现代文件系统(如ext4、XFS)大多采用这种方式或改进版。

2. 文件命名和组织(Naming and Organization)

文件系统提供了一套命名规则,让用户可以用人类可读的名字(如"report.docx"、“vacation.jpg”)来标识文件,而不是使用生硬的物理地址(如"硬盘第1024号扇区")。同时,文件系统支持**目录(Directory)**的概念,让用户可以把相关的文件分组存放,形成层次结构。

这就好比学校的学生管理系统。每个学生有一个学号(类似文件的物理地址),但日常交流中我们使用学生的姓名(类似文件名)。学生们按年级、班级分组(类似目录结构),这样要找"三年级二班的张三"就很容易,而不用在全校几千个学生里一个个翻找。

3. 元数据管理(Metadata Management)

每个文件除了包含实际的数据内容外,还有一堆"关于文件的信息",这些信息叫做元数据(Metadata)。包括:

  • 文件名
  • 文件大小(多少字节)
  • 创建时间
  • 最后修改时间
  • 最后访问时间
  • 文件所有者(哪个用户创建的)
  • 文件权限(谁可以读、谁可以写、谁可以执行)
  • 文件类型(是普通文件、目录、还是链接?)

可以把元数据理解为身份证信息。身份证上记录了你的姓名、性别、出生日期、住址、身份证号等信息,但它本身不是你的"内容"(你的身体、你的思想、你的才华)。元数据也是如此,它描述了文件的特征,但不是文件的实际内容。

4. 数据保护和安全性(Protection and Security)

文件系统需要确保数据不会轻易被损坏或丢失,并且要控制谁可以访问什么文件。

  • 权限控制:文件系统可以设置每个文件的读(Read)、写(Write)、执行(Execute)权限,并且可以分别针对文件所有者、所属用户组、其他用户设置不同的权限。这就像小区的门禁系统:业主有全部权限,访客需要登记,陌生人被拒之门外。

  • 数据完整性:高级文件系统会在数据写入时计算校验和(Checksum),在读取时验证,确保数据没有在存储过程中被意外修改。这就像快递包裹上的封条——如果封条破了,你就知道包裹可能被打开过。

  • 日志功能:现代文件系统使用"日志(Journal)"技术来记录即将进行的操作。如果系统突然断电或崩溃,文件系统可以通过日志恢复到一个一致的状态,避免数据损坏。这就像会计的账本——每做一笔交易先记在账本上,即使中途被打断,也能根据账本恢复。

5. 提供用户接口(User Interface)

文件系统向操作系统和应用程序提供了一套标准的接口(API),让它们可以通过统一的调用来创建、删除、读取、写入、移动文件,而不需要关心底层硬件的具体细节。

这可以理解为餐厅的服务员。你作为顾客不需要知道厨房里的厨师是如何切菜、炒菜、控制火候的,你只需要对服务员说"我要一份宫保鸡丁",服务员会把你的需求传达给厨房,然后把做好的菜端给你。文件系统接口就是这个"服务员",让应用程序不需要直接和硬盘硬件打交道。

3.1.3 Linux支持的文件系统类型

Linux是一个开放的操作系统,它支持非常多的文件系统类型。这就像是Linux这个"翻译官"会说很多种语言,可以和不同"国籍"的存储设备交流。下面我们来详细介绍几种最常见、最重要的Linux文件系统。

ext2(Second Extended File System,第二扩展文件系统)

ext2是Linux早期最经典、使用最广泛的文件系统,于1993年推出。它是ext文件系统的重大升级版本。

核心特点

  • 无日志设计:ext2不使用日志功能。这意味着它的结构简单、性能开销小,在正常运行时读写速度不错。但缺点是如果系统突然崩溃(比如断电),文件系统可能处于不一致的状态,需要花费较长时间进行修复(使用fsck工具扫描整个磁盘)。
  • 支持大文件和大分区:ext2支持最大16TB的文件系统和最大2TB的单个文件(在常见的4KB块大小下)。在1993年,这已经是相当大的容量了。
  • 快速符号链接:对于短路径的符号链接(软链接),ext2直接存放在inode中,不需要额外的数据块,速度很快。

生活中的类比:ext2就像一个传统的纸质账本记账员。他记账很认真,每一笔都写得清清楚楚,读账也很快。但如果记账记到一半突然停电了(他没来得及把笔收好),下次再来的时候,账本可能有些页面只写了一半,需要花很长时间核对哪里出了问题。因为没有"草稿纸"(日志)来记录他本来打算写什么,所以恢复起来很麻烦。

适用场景:由于ext2没有日志开销,它非常适合用于闪存设备(如U盘、SD卡、SSD早期的使用),因为闪存设备的写入次数是有限的,频繁的日志写入会缩短设备寿命。同时,对于只读分区启动映像(如Live CD),ext2也是一个不错的选择,因为这些场景下不会遇到崩溃后恢复的问题。

查看系统中ext2相关信息(虽然现代系统很少用了,但你可能在一些老旧设备或特殊场景中遇到):

# 查看当前系统挂载的文件系统类型
df -T

输出示例:

文件系统       类型       1K-块      已用      可用 已用% 挂载点
/dev/sda1      ext4      10240000   3567123   6672877   35% /
/dev/sdb1      vfat       2096128    104856   1991272    5% /boot/efi
ext3(Third Extended File System,第三扩展文件系统)

ext3于2001年推出,它是ext2的直接继承者,最大的改进就是引入了日志功能(Journaling)

核心特点

  • 日志功能:ext3在ext2的基础上增加了日志层。当进行文件操作时,ext3会先把这些操作记录到日志区域,然后再实际执行。如果系统崩溃,重启后文件系统只需要检查日志区域,就能快速恢复到一致状态,而不需要扫描整个磁盘。
  • 向后兼容ext2:ext3有一个巨大的优势——你可以直接把一个ext2文件系统挂载为ext3(只需开启日志功能),也可以把ext3当作ext2来用(禁用日志)。这种兼容性让用户升级时非常平滑。
  • 三种日志模式
    • journal模式:元数据和文件内容都写日志。最安全,但性能开销最大。
    • ordered模式(默认):只记录元数据,但保证数据在元数据之前写入磁盘。这是安全性和性能的平衡点。
    • writeback模式:只记录元数据,不保证数据写入顺序。性能最好,但安全性最低。

生活中的类比:ext3就像一位聪明的会计,他开始使用草稿纸了。每次做账之前,他先在草稿纸上写下"我要做这三笔账",然后才往正式账本上写。如果写到一半被打断,他下次来只需要看看草稿纸就知道写到哪里了,不需要从头核对整个账本。这大大加快了恢复速度。

创建ext3文件系统的命令示例

# 查看可用的磁盘分区
sudo fdisk -l

# 假设我们要在 /dev/sdb1 上创建ext3文件系统
sudo mkfs.ext3 /dev/sdb1

输出示例:

mke2fs 1.46.5 (30-Dec-2021)
创建含有 2621440 个块(每块 4k)和 655360 个 inode 的文件系统
文件系统 UUID:a1b2c3d4-e5f6-7890-abcd-ef1234567890
超级块的备份存储于下列块:
	32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632

正在分配组表:完成
正在写入 inode 表:完成
创建日志(16384 个块): 完成
写入超级块和文件系统账户统计信息:已完成
ext4(Fourth Extended File System,第四扩展文件系统)

ext4于2008年正式推出,是目前Linux桌面和服务器领域使用最广泛的文件系统。它是ext3的进化版,保留了对ext3/ext2的兼容,同时引入了大量现代化特性。

核心特点

  • 支持超大文件系统和文件:ext4支持最大1EB(Exabyte,约100万TB)的文件系统,以及最大16TB的单个文件。这在今天的数据中心环境中非常重要。

  • Extents存储方式:传统的文件系统(如ext2/ext3)使用"块映射"方式记录文件占用了哪些块,对于大文件,这个映射列表会很长。ext4引入了Extents机制,用一个起始块和一个长度来记录一段连续的存储区域。比如"从第1000块开始,连续占用5000块",而不是列5000个条目。这大大减少了元数据的开销,提高了大文件的性能。

    类比理解:想象你在电影院订座位。传统方式是"第3排5座、第3排6座、第3排7座……“一个个列出。而Extents方式则是"第3排5座开始,连续5个座位”。显然后者更高效。

  • 持久化预分配(Persistent Preallocation):当应用程序需要一个大文件(如数据库、视频编辑的临时文件)时,ext4可以提前分配好空间并标记为"已分配但内容未写入"。这保证了后续写入时一定有空间可用,并且空间是连续的,提高写入速度。

  • 延迟分配(Delayed Allocation):ext4不会立即决定文件数据写入哪个块,而是先在内存中缓存,等到真正需要写入磁盘时再寻找最佳位置。这样可以减少碎片,提高性能。

  • 多块分配器(Multiblock Allocator):一次分配多个块,减少分配操作的次数。

  • 快速的文件系统检查(fsck):ext4在文件系统结构上做了优化,使得fsck检查速度比ext3快很多倍。同时,ext4标记了哪些inode和数据块是未使用的,fsck可以跳过这些区域。

  • 纳秒级时间戳:ext3的时间戳精度是秒级,ext4提升到了纳秒级,对于需要精确时间记录的应用很重要。

  • 在线碎片整理:虽然ext4的碎片问题比ext3好很多,但长期运行后仍可能产生碎片。ext4支持在线碎片整理(不需要卸载文件系统)。

生活中的类比:ext4就像一座现代化的智能仓储物流中心。它用巨大的货架区(Extents)来存放大宗货物,而不是把每个小箱子单独记录位置。它有智能的调度系统(延迟分配、多块分配器),知道怎么安排货物摆放才能最大化利用空间、最小化搬运时间。它有电子备份系统(日志),一旦停电可以快速恢复。它还有高速的盘点系统(快速fsck),几分钟就能核对完整个仓库的库存。

查看ext4文件系统信息的命令

# 查看某个分区的ext4详细信息
sudo tune2fs -l /dev/sda1

输出示例(部分):

tune2fs 1.46.5 (30-Dec-2021)
Filesystem volume name:   <none>
Last mounted on:          /
Filesystem UUID:          xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Filesystem magic number:  0xEF53
Filesystem revision #:    1 (dynamic)
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Default mount options:    user_xattr acl
Filesystem state:         clean
Errors behavior:          Continue
Filesystem OS type:       Linux
Inode count:              655360
Block count:              2621440
Reserved block count:     131072
Free blocks:              2043456
Free inodes:              640234
First block:              0
Block size:               4096
Fragment size:            4096
Group descriptor size:    64
Reserved GDT blocks:      128
Blocks per group:         32768
Inodes per group:         8192
Inode blocks per group:   512
Flex block group size:    16
Filesystem created:       Mon Jan 10 08:30:00 2024
Last mount time:          Sun Jul 27 10:15:32 2024
Last write time:          Sun Jul 27 10:15:32 2024
Mount count:              5
Maximum mount count:      -1
Last checked:             Mon Jan 10 08:30:00 2024
Check interval:           0 (<none>)
Lifetime writes:          45 GB
Reserved blocks uid:      0 (user root)
Reserved blocks gid:      0 (group root)
First inode:              11
Inode size:               256
Required extra isize:     32
Desired extra isize:      32
Journal inode:            8
Default directory hash:   half_md4
Directory Hash Seed:      xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Journal backup:           inode blocks

创建ext4文件系统的命令

# 创建ext4文件系统
sudo mkfs.ext4 /dev/sdc1

# 创建时指定卷标(给文件系统起个名字)
sudo mkfs.ext4 -L "MyData" /dev/sdc1

# 创建时保留一定比例的空间给root用户(默认5%)
sudo mkfs.ext4 -m 1 /dev/sdc1  # 只保留1%
XFS(eXtended File System)

XFS最初由Silicon Graphics(SGI)公司在1993年为IRIX操作系统开发,后来移植到了Linux。它是目前大型企业环境、数据中心和高性能计算领域非常流行的文件系统。

核心特点

  • 极高的可扩展性:XFS支持最大8EB的文件系统,以及最大8EB的单个文件。对于需要存储海量数据的企业级应用来说,XFS是不二之选。

  • 优秀的并发性能:XFS在设计上非常擅长处理大量并发的文件操作。它使用**分配组(Allocation Groups)**技术,将文件系统划分为多个独立的区域,每个区域可以独立进行空间分配和inode管理。多个CPU核心可以同时操作不同的分配组,大大提升了多核系统上的性能。

    类比理解:想象一个巨大的超市,XFS把这个超市分成了几十个独立区域,每个区域都有自己的收银员和货架管理员。顾客可以同时在这几十个区域结账,互不干扰。而传统的文件系统可能只有一个收银台,所有人都要排队。

  • 快速的分配和删除:XFS使用B+树来管理空闲空间,分配新空间非常快。特别是删除大文件时,XFS的性能远优于ext系列文件系统,因为它不需要逐个标记块为空闲,而是直接更新B+树中的记录。

  • 在线扩容:XFS可以在文件系统挂载(正在使用)的情况下进行扩容。虽然XFS不支持在线缩容,但在服务器环境中,存储需求通常是只增不减的,所以在线扩容已经足够实用。

  • 延迟日志(Delayed Logging):XFS的日志机制非常高效,将多个小日志合并成大块写入,减少磁盘I/O。

生活中的类比:XFS就像一座国际机场的行李处理系统。机场每天要处理几十万件行李,这些行李大小不一(从小手提包到大行李箱),需要快速分配到各个航班的货舱中,并在到达后快速分拣出来。行李系统使用很多条并行的传送带(分配组),每条传送带独立工作;同时用高度智能的调度系统(B+树)来追踪每件行李的位置。无论是"托运"(创建文件)、“取行李”(读取文件)还是"丢弃"(删除文件),系统都能高效处理。

XFS相关的命令示例

# 创建XFS文件系统
sudo mkfs.xfs /dev/sdd1

# 创建时指定较大的分配组大小(适合大容量磁盘)
sudo mkfs.xfs -d agcount=32 /dev/sdd1

# 查看XFS文件系统信息
sudo xfs_info /dev/sdd1

输出示例:

meta-data=/dev/sdd1              isize=512    agcount=4, agsize=655360 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=1        finobt=1, sparse=1, rmapbt=0
         =                       reflink=1    bigtime=1 inobtcount=1
data     =                       bsize=4096   blocks=2621440, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0, ftype=1
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
Btrfs(B-tree File System,B树文件系统)

Btrfs是一个相对较新的文件系统,由Oracle在2007年开始开发,被誉为"Linux的下一代文件系统"。它设计目标非常宏大,要集成传统上由独立工具完成的功能。

核心特点

  • 写时复制(Copy-on-Write, COW):Btrfs的核心设计原则。当你修改一个文件时,Btrfs不会直接覆盖旧数据,而是把修改后的数据写到新的位置,然后更新指针指向新数据。旧数据保持不变,直到新数据写入成功后才释放旧空间。这天然保证了数据一致性,并且让创建快照变得非常容易。

    类比理解:想象你在用Word写一份重要报告。传统的保存方式是直接覆盖原文件(如果断电,文件可能损坏)。而COW就像"另存为"——每次保存都创建一个新版本,旧版本还在。你随时可以回退到之前的版本。

  • 内置快照和子卷(Snapshots and Subvolumes):Btrfs可以在瞬间创建文件系统的快照(Snapshot),因为快照只是复制了元数据的指针,而不是复制所有数据。快照占用的空间极小,只有发生修改的部分才会额外占用空间。子卷就像文件系统中的"独立分区",但比传统分区灵活得多。

  • 内置数据校验和:Btrfs会对所有数据和元数据计算校验和,自动检测数据损坏(“比特翻转”)。如果发现数据损坏,且你有RAID配置,Btrfs可以自动从其他副本恢复正确数据。

  • 内置RAID支持:Btrfs可以在文件系统层面实现RAID 0、1、5、6、10等配置,而不需要硬件RAID卡或mdadm软件RAID。这简化了存储管理。

  • 在线压缩:Btrfs支持透明的在线压缩(zlib、lzo、zstd),文件在写入时自动压缩,读取时自动解压,对用户完全透明。对于文本文件、日志文件等可压缩数据,可以显著节省空间。

  • 去重(Deduplication):Btrfs可以识别并删除重复的数据块,只保留一份副本。在虚拟化环境或备份场景中,这可以节省大量空间。

  • 动态inode分配:传统文件系统(如ext4)在创建时需要预先分配固定数量的inode。如果小文件很多,可能inode先用完但空间还有剩余;如果大文件很多,可能inode浪费。Btrfs的inode是动态分配的,没有这个问题。

生活中的类比:Btrfs就像一座未来派的智能住宅。这座房子有"时间倒流"功能(快照),你可以随时回到昨天、上周的家居布置状态。它有"自我修复"能力(校验和和RAID),如果某块墙壁褪色了,它能自动从备份中还原。它有"智能收纳"功能(压缩和去重),会自动把不常用的东西真空压缩存放。它有"模块房间"(子卷),你可以灵活调整房间布局而不需要重新装修。虽然这座房子很先进,但也因为功能太复杂,偶尔会有一些小毛病(Btrfs在早期版本中确实存在一些稳定性问题,但近年来已经大幅改善)。

Btrfs相关命令示例

# 创建Btrfs文件系统
sudo mkfs.btrfs /dev/sde1

# 使用多个设备创建Btrfs RAID1
sudo mkfs.btrfs -d raid1 -m raid1 /dev/sde1 /dev/sdf1

# 查看Btrfs文件系统信息
sudo btrfs filesystem show

输出示例:

Label: none  uuid: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
	Total devices 1 FS bytes used 2.34GiB
	devid    1 size 100.00GiB used 5.02GiB path /dev/sde1

# 创建子卷
sudo btrfs subvolume create /mnt/btrfs_data/my_subvolume

# 创建快照
sudo btrfs subvolume snapshot /mnt/btrfs_data/my_subvolume /mnt/btrfs_data/my_subvolume_snapshot

# 查看子卷列表
sudo btrfs subvolume list /mnt/btrfs_data
其他文件系统简介

除了上述几种主流文件系统,Linux还支持很多其他文件系统,了解它们有助于你在不同场景下做出正确选择:

  • ReiserFS/Reiser4:由Namesys公司开发,以小文件性能著称。在大量小文件的场景下(如邮件服务器),ReiserFS曾经非常流行。但由于开发团队的一些问题,现在已较少使用。

  • JFS(Journaled File System):IBM开发的日志文件系统,以低CPU占用和高效率著称。适合CPU资源紧张的环境。

  • ZFS(Zettabyte File System):由Sun Microsystems开发,功能与Btrfs类似(快照、校验和、RAID、压缩等),但更加成熟稳定。由于许可证不兼容,ZFS不能直接被包含在Linux内核中,但可以通过DKMS或OpenZFS项目使用。ZFS在NAS(网络存储)领域非常流行。

  • F2FS(Flash-Friendly File System):由三星开发,专门为闪存设备(SSD、eMMC、SD卡)优化。它采用日志结构(Log-structured)设计,减少闪存的写入放大(Write Amplification),延长闪存寿命。现在许多安卓手机的内部存储就使用F2FS。

  • VFAT/exFAT/NTFS:这些主要是Windows使用的文件系统。Linux通过驱动可以读写这些文件系统,用于和Windows交换数据。VFAT是FAT32的扩展,支持长文件名;exFAT是大容量闪存的标准格式;NTFS是Windows NT系列的默认文件系统。

  • tmpfs:这是一个特殊的"基于内存"的文件系统。把文件存放在tmpfs上,实际上是把文件存放在RAM(内存)中。速度极快,但断电后数据会丢失。常用于/tmp目录或临时缓存。

  • procfs/sysfs/devtmpfs:这些是Linux的虚拟文件系统,不存储实际数据,而是提供内核和系统信息的接口。我们将在后面的小节中详细介绍它们。

文件系统选择建议

对于零基础学习者,你不需要现在就掌握所有文件系统的细节,但这里有一个简单的选择指南供你参考:

使用场景 推荐文件系统 原因
日常桌面Linux系统 ext4 稳定、成熟、性能好、社区支持广泛
大容量数据存储/服务器 XFS 扩展性好、大文件性能优秀、并发处理强
需要快照和高级功能 Btrfs 内置快照、校验和、压缩、去重
闪存设备(U盘/SD卡) F2FS 或 ext4(无日志模式) 延长闪存寿命
临时文件/缓存 tmpfs 速度极快,基于内存
与Windows交换数据 exFAT/VFAT 兼容性最好

3.2 Linux目录结构全景图

3.2.1 树形结构:一切从根开始

当你第一次打开Linux系统,打开文件管理器时,你可能会注意到一个和Windows非常不同的地方:Windows有C盘、D盘、E盘,每个盘都有自己的根目录;而Linux只有一个"/“符号,一切文件和目录都从这个”/"开始延伸出去,像一棵大树一样。

这就是Linux的树形目录结构

让我们用一个形象的类比来理解这种结构。想象一棵巨大的家族树:在最顶端是"始祖"(根目录/),始祖有若干子女(/bin、/etc、/home、/usr等),每个子女又有自己的子女(比如/home下面有/user1、/user2等),以此类推。任何一个家族成员(文件或目录)都可以通过一条从始祖到他本人的路径来唯一确定。

在Linux中:

  • **/(斜杠)**就是这棵树的根,所有的目录和文件都从它开始。
  • **目录(Directory)**就是树的分叉点,它可以包含其他目录或文件。
  • **文件(File)**就是树的叶子,是最终存储数据的地方。

Linux中的一切都是文件。你的硬盘、键盘、鼠标、显示器,甚至系统的内存和CPU信息,在Linux中都以"文件"的形式呈现。这听起来有些不可思议,但这是Linux设计哲学的核心之一,也是它如此强大和统一的原因。

类比加深理解

  • 树形结构 = 国家的行政区划:一个国家的最高行政单位是中央政府(/),下面有省(/usr、/etc、/home等),省下面有市,市下面有县,县下面有镇,镇下面有村。任何一个地址都可以写成:中国/某省/某市/某县/某镇/某村/某户。这个地址从国家层面一步步精确到具体住户,不会有歧义。

  • 树形结构 = 图书馆的分类编目:图书馆的目录从"总馆"开始,下面分"文学部"、“科学部”、“历史部"等,每个部下面再分"中国文学”、“外国文学”,再下面是"古代文学"、“现代文学”,最后是具体的书名。任何一本书都可以通过一条完整的分类路径找到。

3.2.2 Linux与Windows目录结构的区别

如果你是Windows用户,你可能对C:\Windows\System32这样的路径很熟悉。Linux和Windows的目录结构有本质的不同,理解这些差异对于你适应Linux至关重要。

对比维度 Windows Linux
根目录形式 每个分区有自己的根(C:\、D:\、E:\) 只有一个全局根目录(/)
路径分隔符 反斜杠(\) 正斜杠(/)
目录结构 分区相互独立,类似多个并行的树 统一的树形结构,分区挂载到树的某个分支
命名区分大小写 不区分(File.txt 和 file.txt 是同一个文件) 区分(File.txt 和 file.txt 是两个不同文件)
特殊文件存放位置 系统文件主要在C:\Windows 系统文件分散在/bin、/sbin、/lib、/etc等目录
用户数据默认位置 C:\Users\用户名 /home/用户名
程序安装位置 通常分散在各处,注册表记录位置 主要在/bin、/sbin、/usr/bin、/usr/local/bin等
设备文件 通过专门的API访问,不可见为文件 以文件形式存在于/dev目录

核心区别的深入解释

1. 单一根 vs 多根

Windows的每个分区(C盘、D盘)都是一个独立的"小王国",有自己的根目录。你在C盘里看不到D盘的内容,除非通过"我的电脑"进入D盘。这就像是几栋独立的公寓楼,每栋楼有自己的门牌号系统,楼与楼之间不互通。

Linux只有一个根目录/,所有的分区、硬盘、U盘、光盘,都以"挂载"的方式接入到这个统一的大树中的某个分支上。比如,你的第二个硬盘可能挂载到/mnt/data目录下,你访问/mnt/data/document.txt就像访问任何其他文件一样自然。这就像是一座巨大的连体建筑,虽然有很多 wing(侧翼),但内部是完全连通的,你只需要知道房间号就能找到任何地方。

2. 分区挂载机制

在Linux中,“分区"和"目录树"是分离的概念。你可以把分区想象成一个个"存储容器”,而目录树是"访问路径"。通过mount命令,你可以把一个存储容器挂接到目录树的任何一个位置。

比如:

# 把一个硬盘分区挂载到 /mnt/mydisk 目录
sudo mount /dev/sdb1 /mnt/mydisk

# 现在访问 /mnt/mydisk/file.txt 就是在访问那个分区上的文件

这就像是商场里的品牌专柜:整个商场是一个统一的建筑(目录树),但每个专柜(分区)可以由不同的商家经营(存储不同的数据)。顾客不需要知道哪个专柜属于哪个商家,只需要知道它在商场的哪一层、哪个位置就能找到。

3. 大小写敏感

Linux的文件名是区分大小写的。在Linux中:

  • Document.txt
  • document.txt
  • DOCUMENT.TXT
  • DoCuMeNt.TxT

这是四个完全不同的文件!这一点对于从Windows转过来的用户特别容易踩坑。在Windows中,上面四个名字指的是同一个文件。

这就像英语中的大写和小写字母:“Apple”(苹果公司)和"apple"(苹果水果)在英语中是不同的含义。Linux把文件名当作严格区分大小写的字符串来处理。

3.2.3 FHS标准:Linux目录的"宪法"

你有没有想过,为什么不同发行版的Linux(Ubuntu、CentOS、Debian、Fedora等)的目录结构都差不多?为什么/bin、/etc、/usr这些目录在每个Linux系统中都存在?这是因为有一个叫做**FHS(Filesystem Hierarchy Standard,文件系统层次结构标准)**的规范在起作用。

FHS就像Linux目录结构的"宪法",它规定了每个标准目录的用途、应该存放什么类型的文件。所有主流的Linux发行版都遵循或基本遵循FHS标准,这就保证了:

  1. 一致性:无论你用哪个Linux发行版,关键目录的位置和用途都是一样的。
  2. 可预测性:开发者知道应该把配置文件放在哪里,用户知道去哪里找日志。
  3. 兼容性:遵循FHS的程序可以在不同发行版上正常工作。

FHS将目录分为两大类:

1. 可共享的(Sharable) vs 不可共享的(Unsharable)

  • 可共享:这些目录中的文件可以在不同主机之间共享。比如/usr(程序)、/home(用户数据)。在一个网络环境中,/usr和/home可以挂载到网络上,多台计算机共用。
  • 不可共享:这些目录中的文件是特定于某台主机的,不能共享。比如/etc(配置文件)、/boot(启动文件)。

2. 静态的(Static) vs 可变的(Variable)

  • 静态:这些目录中的文件不会自动变化(除非管理员手动修改)。比如/bin、/sbin、/usr、/opt。
  • 可变:这些目录中的文件在系统运行过程中会不断变化。比如/var(日志、缓存)、/tmp(临时文件)、/home(用户数据)。

这两类组合起来,就形成了四种目录类型:

类型 示例 说明
可共享且静态 /usr、/opt 可以在网络中共享,内容相对稳定
可共享且可变 /var/mail、/home 可以在网络中共享,内容经常变化
不可共享且静态 /etc、/boot 特定于本机,内容相对稳定
不可共享且可变 /var/run、/var/lock 特定于本机,内容经常变化

FHS标准规定的核心目录结构(我们将在下一节详细解析每个目录):

/                   <- 根目录,一切的开始
├── bin             <- 基本用户命令
├── boot            <- 启动加载器文件
├── dev             <- 设备文件
├── etc             <- 系统配置文件
├── home            <- 普通用户主目录
├── lib             <- 基本共享库
├── lib64           <- 64位基本共享库
├── media           <- 可移动媒体挂载点
├── mnt             <- 临时挂载点
├── opt             <- 附加应用软件包
├── proc            <- 进程信息的虚拟文件系统
├── root            <- root用户主目录
├── run             <- 运行时的变量数据
├── sbin            <- 基本系统管理命令
├── srv             <- 本机服务数据
├── sys             <- 系统信息的虚拟文件系统
├── tmp             <- 临时文件
├── usr             <- 二级层次结构
│   ├── bin         <- 用户命令
│   ├── include     <- C程序头文件
│   ├── lib         <- 库文件
│   ├── local       <- 本地安装软件
│   ├── sbin        <- 非关键的系统命令
│   ├── share       <- 架构无关数据
│   └── src         <- 源代码
└── var             <- 可变数据
    ├── cache       <- 应用程序缓存
    ├── lib         <- 可变状态信息
    ├── log         <- 日志文件
    ├── mail        <- 用户邮箱
    ├── run         <- 运行数据(已迁移到/run)
    ├── spool       <- 任务队列
    └── tmp         <- 重启后保留的临时文件

生活中的类比:FHS就像城市的城市规划法规。它规定了商业区在哪里(/usr/bin)、住宅区在哪里(/home)、市政设施在哪里(/etc)、垃圾处理站在哪里(/tmp)、图书馆在哪里(/usr/share/doc)。不同的开发商(Linux发行版)可以在法规框架内建设自己的特色项目,但基本的城市骨架是一致的。这样,无论你是第一次来北京、上海还是广州,你都知道"市政府"大致是管什么的,"商业街"在哪里找。


3.3 根目录 / 下的核心目录解析

现在,让我们像探险家一样,一步步深入Linux的根目录,揭开每个核心目录的神秘面纱。我会用大量的类比帮助你理解这些目录的作用,并给出实用的命令示例。

3.3.1 /bin 目录:系统启动的"救命工具箱"

全称:binaries(二进制可执行文件)

作用:/bin目录存放的是系统启动和单用户模式下必需的基本用户命令。所谓"单用户模式",是系统的一种特殊维护状态,在这种状态下系统只加载最基本的服务,通常用于修复故障。即使在单用户模式下,/bin中的命令也必须是可用的。

包含的典型命令

  • ls(列出目录内容)
  • cp(复制文件)
  • mv(移动/重命名文件)
  • rm(删除文件)
  • cat(查看文件内容)
  • echo(输出文本)
  • mkdir(创建目录)
  • pwd(显示当前路径)
  • sh(基本的shell解释器)
  • mount / umount(挂载/卸载文件系统)
  • chmod(修改权限)
  • df(查看磁盘空间)

类比理解:/bin就像一个急救医疗箱。无论你身在何处(什么运行级别),遇到紧急情况时,这个箱子里的基本工具(绷带、消毒液、止痛药)必须随手可用。没有这些工具,你连最基本的自救都做不到。

查看/bin目录内容的命令

ls /bin

输出示例(部分,实际输出很长):

[          chmod      df         kill       mkdir      mv         pwd        sh         true       umount
]          chown      dir        kmod       mknod      nano       rbash      sleep      umask      uname
arch       cp         dmesg      less       mktemp     netstat    readlink   sort       uncompress
awk        cpio       dnsdomainname  ln       more       nice       rm         stty       unicode_start
bash       csh        domainname  login     mount      nisdomainname  rmdir      su         vdir
cat        dash       echo       ls        mt         ps         sed        sync       ypdomainname

3.3.2 /sbin 目录:管理员的"专属工具箱"

全称:system binaries(系统二进制文件)

作用:/sbin目录存放的是系统管理命令,这些命令通常只有root用户(系统管理员)才需要执行,用于系统维护、网络配置、磁盘管理等高级操作。普通用户虽然可能在PATH中包含/sbin,但执行这些命令时通常会因为权限不足而被拒绝(除非使用sudo)。

包含的典型命令

  • fdisk(磁盘分区工具)
  • mkfs(创建文件系统)
  • fsck(文件系统检查和修复)
  • reboot / halt / shutdown(重启/关机)
  • ifconfig / ip(网络配置)
  • route(路由表管理)
  • swapon / swapoff(交换空间管理)
  • iptables / nftables(防火墙配置)
  • init / systemctl(系统和服务管理)

类比理解:/sbin就像飞机驾驶舱里的控制面板。普通乘客(普通用户)不需要也不应该碰这些按钮和开关。只有机长和副驾驶(root管理员)才有权限操作。这些控制可以调整发动机推力(重启系统)、改变航向(配置网络)、检查燃油系统(磁盘检查)——每一项都关系到整架飞机的安全。

查看/sbin目录内容的命令

ls /sbin

输出示例(部分):

addgroup       e2fsck         ip              mke2fs          routel
adduser        e2label        iptables        mkfs            setcap
agetty         fdisk          iptables-save   mkfs.btrfs      sfdisk
arp            findfs         isosize         mkfs.ext2       shadowconfig
badblocks      fsck           killall5        mkfs.ext3       shutdown
blkdiscard     fsck.cramfs    ldconfig        mkfs.ext4       start-stop-daemon
blkid          fsck.ext2      logsave         mkfs.minix      sulogin
blockdev       fsck.ext3      losetup         mkswap          swaplabel
bridge         fsck.ext4      lsmod           modprobe        swapoff
cfdisk         fsck.minix     mii-tool        mount.nfs       swapon
chpasswd       fstab-decode   mkdosfs         nameif          switch_root
ctrlaltdel     fstrim         mke2fs          pivot_root      sysctl
debugfs        getty          mkfs            poweroff        tc

3.3.3 /lib 和 /lib64 目录:程序的"共享零件库"

全称:libraries(库文件)

作用:/lib目录存放的是启动系统和运行/bin、/sbin中命令所必需的基本共享库。共享库(Shared Library)是程序运行时需要调用的公共代码模块。多个程序可以共享同一个库文件,避免了重复存储,节省了磁盘空间和内存。

/lib64是64位系统的专用目录,存放64位版本的库文件。在纯32位系统上,所有库都放在/lib中。在现代64位Linux上,/lib通常是一个指向/usr/lib的符号链接,/lib64是一个指向/usr/lib64的符号链接。

什么是共享库?类比理解

想象你要组装很多个家具(运行很多程序)。每个家具都需要螺丝、螺母、扳手等零件(库函数)。如果没有共享库,每个家具的包装盒里都要放一套完整的工具。如果你有100个家具,就有100套重复的工具,非常浪费。

共享库就像是小区里的公共工具房。所有居民(程序)都可以去工具房里借用需要的工具(调用库函数)。工具房里有一套完整的工具,大家共用,大大节省了空间和成本。

在Linux中,共享库的文件名通常以.so结尾(Shared Object),后面跟着版本号,比如:

  • libc.so.6:C语言标准库,几乎所有程序都需要它
  • libm.so.6:数学函数库
  • libdl.so.2:动态加载库
  • libpthread.so.0:线程库

查看/lib64目录内容的命令

ls /lib64 | head -20

输出示例:

audit
cracklib_dict.hwm
cracklib_dict.pwd
cracklib_dict.pwi
e2fsprogs
ld-linux-x86-64.so.2
libacl.so.1
libacl.so.1.1.2253
libaio.so.1
libaio.so.1.0.1
libattr.so.1
libattr.so.1.1.2501
libaudit.so.1
libaudit.so.1.0.0
libblkid.so.1
libblkid.so.1.1.0
libBrokenLocale-2.28.so
libBrokenLocale.so.1
libcap-ng.so.0
libcap-ng.so.0.0.0

查看程序依赖哪些库

# 查看 ls 命令依赖哪些共享库
ldd /bin/ls

输出示例:

	linux-vdso.so.1 (0x00007ffcc5bfe000)
	libselinux.so.1 => /lib64/libselinux.so.1 (0x00007f8b8c4a0000)
	libcap.so.2 => /lib64/libcap.so.2 (0x00007f8b8c49a000)
	libacl.so.1 => /lib64/libacl.so.1 (0x00007f8b8c490000)
	libc.so.6 => /lib64/libc.so.6 (0x00007f8b8c2d0000)
	libpcre2-8.so.0 => /lib64/libpcre2-8.so.0 (0x00007f8b8c236000)
	libdl.so.2 => /lib64/libdl.so.2 (0x00007f8b8c230000)
	libattr.so.1 => /lib64/libattr.so.1 (0x00007f8b8c228000)
	libpthread.so.0 => /lib64/libpthread.so.0 (0x00007f8b8c206000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f8b8c4ea000)

3.3.4 /boot 目录:系统的"启动引擎"

作用:/boot目录存放的是启动Linux系统所需的文件。包括Linux内核(操作系统的核心)、初始内存磁盘(initramfs/initrd,用于启动时加载必要的驱动)、引导加载器(GRUB)的配置文件等。

包含的典型文件

  • vmlinuz-*:压缩的Linux内核镜像
  • initramfs-*.imginitrd-*:初始内存磁盘镜像
  • grub/grub2/:GRUB引导加载器的配置文件
  • config-*:编译内核时使用的配置文件
  • System.map-*:内核符号表

类比理解:/boot就像汽车的发动机舱和点火系统。你每天开车时不会打开引擎盖去碰里面的东西,但没有发动机舱里的引擎、电池、点火装置,汽车根本发动不起来。/boot目录平时基本不动,但它是整个系统启动的第一站。

重要提示:/boot目录通常需要放在一个文件系统简单、引导加载器能够识别的分区上。在现代系统上,/boot通常单独放在一个较小的分区(比如500MB-1GB),并且使用ext4等引导加载器支持良好的文件系统。

查看/boot目录内容的命令

ls -lh /boot

输出示例:

总用量 120M
-rw-r--r-- 1 root root   217K 1月  10 08:30 config-5.14.0-362.el9.x86_64
drwxr-xr-x 3 root root  4.0K 7月  27 10:15 efi
drwxr-xr-x 2 root root  4.0K 7月  27 10:15 grub2
-rw------- 1 root root   120M 7月  27 10:15 initramfs-0-rescue-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.img
-rw------- 1 root root    45M 1月  15 09:20 initramfs-5.14.0-362.el9.x86_64.img
-rw-r--r-- 1 root root    12M 1月  15 09:20 initramfs-5.14.0-362.el9.x86_64kdump.img
-rw-r--r-- 1 root root   4.0M 1月  10 08:30 System.map-5.14.0-362.el9.x86_64
-rwxr-xr-x 1 root root   12M 1月  10 08:30 vmlinuz-0-rescue-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-rwxr-xr-x 1 root root   12M 1月  10 08:30 vmlinuz-5.14.0-362.el9.x86_64

3.3.5 /dev 目录:设备的"化身大厅"

全称:devices(设备)

作用:/dev目录是Linux最神奇的地方之一。它存放的不是普通的文件,而是设备文件(Device Files)。在Linux的设计哲学中,“一切皆文件”,所以所有的硬件设备——硬盘、键盘、鼠标、显示器、打印机、声卡、USB设备——都以文件的形式出现在/dev目录中。

通过读写这些设备文件,程序可以和硬件设备进行交互。比如,向/dev/tty1写入文本,文本就会显示在第一个虚拟终端上;读取/dev/input/mice,就能得到鼠标的移动数据。

常见的设备文件

设备文件 说明
/dev/sda 第一个SCSI/SATA硬盘
/dev/sda1 第一个硬盘的第一个分区
/dev/sdb 第二个SCSI/SATA硬盘
/dev/nvme0n1 第一个NVMe固态硬盘
/dev/nvme0n1p1 第一个NVMe硬盘的第一个分区
/dev/tty* 终端设备
/dev/console 系统控制台
/dev/null “黑洞”,写入的数据会消失,读取永远返回EOF
/dev/zero 读取时返回无限的空字节(0x00)
/dev/random 真随机数生成器
/dev/urandom 伪随机数生成器(非阻塞)
/dev/full 写入时返回"设备已满"错误
/dev/loop* 循环设备,用于挂载镜像文件
/dev/cdrom 光驱(通常是符号链接)
/dev/stdin 标准输入
/dev/stdout 标准输出
/dev/stderr 标准错误输出

类比理解:/dev就像剧场的后台化妆间。每个演员(硬件设备)在这里都有一个专属的化妆台(设备文件)。导演(应用程序)不需要直接冲进演员家里去指挥他,只需要在化妆间里给演员递个纸条(读写设备文件),演员就知道该怎么表演了。最神奇的是,有些"演员"不是真实的人,而是特效装置——比如/dev/null是一个"无底洞",你把任何东西扔进去都会消失;/dev/zero是一个"永无止境的空白纸卷",你可以一直从上面撕下写着0的纸条。

有趣的设备文件演示

# /dev/null 演示:把不需要的输出丢进"黑洞"
ls /some_nonexistent_path 2> /dev/null   # 错误信息被丢弃,什么都不显示

# /dev/zero 演示:创建一个大文件(填满0)
dd if=/dev/zero of=/tmp/bigfile bs=1M count=100   # 创建一个100MB的零填充文件

# /dev/urandom 演示:生成随机数据
head -c 32 /dev/urandom | xxd    # 读取32字节的随机数据并以十六进制显示

# /dev/full 演示:模拟磁盘满
echo "test" > /dev/full   # 会报错:设备上没有空间

查看/dev目录内容的命令

ls -l /dev | head -20

输出示例:

总用量 0
crw-r--r-- 1 root root     10,   235 7月  27 10:15 autofs
drwxr-xr-x 2 root root         540 7月  27 10:15 block
drwxr-xr-x 2 root root          80 7月  27 10:15 bsg
drwxr-xr-x 3 root root          60 7月  27 10:15 bus
drwxr-xr-x 2 root root        3160 7月  27 10:15 char
crw------- 1 root root      5,     1 7月  27 10:15 console
lrwxrwxrwx 1 root root          11 7月  27 10:15 core -> /proc/kcore
drwxr-xr-x 3 root root          60 7月  27 10:15 cpu
crw------- 1 root root     10,    60 7月  27 10:15 cpu_dma_latency
drwxr-xr-x 7 root root         140 7月  27 10:15 disk
brw-rw---- 1 root disk    253,     0 7月  27 10:15 dm-0
brw-rw---- 1 root disk    253,     1 7月  27 10:15 dm-1
brw-rw---- 1 root disk    253,     2 7月  27 10:15 dm-2
drwxr-xr-x 2 root root          60 7月  27 10:15 dri
crw-rw---- 1 root video    29,     0 7月  27 10:15 fb0
lrwxrwxrwx 1 root root          13 7月  27 10:15 fd -> /proc/self/fd
crw-rw-rw- 1 root root      1,     7 7月  27 10:15 full
drwxr-xr-x 3 root root          60 7月  27 10:15 hugepages

注意输出中的第一个字符:

  • c 表示字符设备(character device),按字符流方式读写,如终端、串口。
  • b 表示块设备(block device),按块方式读写,如硬盘、分区。
  • l 表示符号链接(symbolic link)。
  • d 表示目录。

3.3.6 /proc 目录:内核的"直播大厅"

全称:processes(进程)/ proc filesystem

作用:/proc是一个虚拟文件系统(Virtual Filesystem),它不占用任何磁盘空间,所有数据都是内核在内存中动态生成的。/proc提供了一个查看和修改内核运行时信息的接口。你可以把它理解为内核对外开放的"实时直播"窗口。

通过/proc,你可以查看:

  • 每个运行中进程的详细信息(/proc/PID/)
  • CPU信息(/proc/cpuinfo)
  • 内存使用情况(/proc/meminfo)
  • 内核版本和参数(/proc/version、/proc/cmdline、/proc/sys/)
  • 已加载的内核模块(/proc/modules)
  • 网络状态(/proc/net/)
  • 已挂载的文件系统(/proc/mounts)

类比理解:/proc就像医院的监护仪屏幕。病人(操作系统)躺在床上,身上连接了各种传感器。监护仪实时显示心跳、血压、血氧、体温等数据。这些数据不是存在某个文件夹里的,而是仪器实时从病人身上采集的。医生(管理员/用户)可以通过这些数据了解病人的状况,甚至在某些情况下调整治疗参数(通过写入/proc中的某些文件来修改内核参数)。

/proc中的常用文件演示

# 查看CPU详细信息
cat /proc/cpuinfo

输出示例(部分):

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 142
model name	: Intel(R) Core(TM) i7-10510U CPU @ 1.80GHz
stepping	: 12
microcode	: 0xf0
cpu MHz		: 2299.998
cache size	: 8192 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 4
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 22
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx rdtscp lm constant_tsc rep_good nopl xtopology nonstop_tsc cpuid pni pclmulqdq ssse3 cx16 sse4_1 sse4_2 movbe popcnt aes rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single pti fsgsbase bmi1 bmi2 invpcid rdseed clflushopt md_clear flush_l1d arch_capabilities
bugs		: cpu_meltdown spectre_v1 spectre_v2 spec_store_bypass l1tf mds swapgs itlb_multihit srbds mmio_unknown
bogomips	: 4607.99
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:
# 查看内存使用情况
cat /proc/meminfo

输出示例(部分):

MemTotal:        8008460 kB
MemFree:         1234567 kB
MemAvailable:    4567890 kB
Buffers:          123456 kB
Cached:          3456789 kB
SwapCached:            0 kB
Active:          2345678 kB
Inactive:        1234567 kB
Active(anon):    1234567 kB
Inactive(anon):   234567 kB
Active(file):    1111111 kB
Inactive(file):  1000000 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:       1048572 kB
SwapFree:        1048572 kB
# 查看当前进程的PID
# $$ 表示当前shell的进程ID
cat /proc/$$/cmdline ; echo

# 查看某个进程打开的文件(以当前shell为例)
ls -l /proc/$$/fd

输出示例:

总用量 0
lrwx------ 1 user user 64 7月  27 14:30 0 -> /dev/pts/0
lrwx------ 1 user user 64 7月  27 14:30 1 -> /dev/pts/0
lrwx------ 1 user user 64 7月  27 14:30 2 -> /dev/pts/0
lr-x------ 1 user user 64 7月  27 14:30 3 -> /proc/1234/fd

3.3.7 /sys 目录:硬件设备的"户籍档案室"

全称:system(系统)/ sysfs

作用:/sys也是一个虚拟文件系统,在系统启动时由内核挂载。它的主要目的是向用户空间暴露内核数据结构、内核参数和硬件设备信息。与/proc侧重于进程信息不同,/sys更侧重于设备和驱动程序的信息。

/sys以结构化的方式组织设备和总线信息:

  • /sys/block/:所有块设备(硬盘等)
  • /sys/bus/:系统总线(PCI、USB、SCSI等)
  • /sys/class/:按类别组织的设备(如net、tty、block等)
  • /sys/devices/:所有设备的层次结构
  • /sys/module/:已加载的内核模块
  • /sys/fs/:文件系统相关信息
  • /sys/kernel/:内核配置和调试信息

类比理解:/sys就像政府的户籍档案管理系统。每个公民(硬件设备)都有一个档案,记录了身份证号(设备ID)、家庭住址(总线位置)、父母信息(驱动程序)、身体状况(设备状态)等。政府(内核)用这套系统管理所有公民,而市民(用户/程序)可以通过合法的查询渠道(读/sys中的文件)来了解这些信息。

查看/sys目录内容的命令

# 查看系统中的块设备
ls /sys/block/

输出示例:

dm-0  dm-1  dm-2  loop0  loop1  loop2  sr0
# 查看某个块设备的大小(以扇区为单位,通常每个扇区512字节)
cat /sys/block/sda/size
# 如果系统中没有sda,可以用dm-0等替代
cat /sys/block/dm-0/size
# 查看网络接口信息
ls /sys/class/net/

输出示例:

eth0  lo
# 查看eth0网卡的MAC地址
cat /sys/class/net/eth0/address

输出示例:

00:16:3e:12:34:56

3.3.8 /run 目录:系统的"临时便签板"

作用:/run目录存放的是系统启动后生成的运行时数据。这些数据在系统重启后会被清空。典型的内容包括:

  • 进程ID文件(PID files):如/run/nginx.pid
  • 通信套接字(Sockets):如/run/dbus/system_bus_socket
  • 临时状态文件:如/run/utmp(记录当前登录用户)

/run是现代Linux系统(systemd时代)引入的目录,它替代了以前分散在/var/run和/var/lock中的运行时数据。/run通常被挂载为tmpfs(基于内存的文件系统),所以读写速度极快。

类比理解:/run就像餐厅前台的白板。白板上写着"当前有多少桌客人在用餐"、“哪些菜已经上齐”、"哪些厨师在岗"等实时信息。这些信息在一天营业结束后就被擦掉(系统重启),第二天重新开始记录。白板上的信息变化很快,不需要长期保存。

查看/run目录内容的命令

ls /run

输出示例(部分):

agetty.reload  cron.reboot    faillock       initramfs      log            mount          rpcbind        systemd        user
atd.pid        cryptsetup     fsck           lock           lvm            NetworkManager screen         tmpfiles.d     utmp
auditd.pid     dbus           gdm3           initctl        machine-id     plymouth       sendsigs.omit  udev           xtables.lock
console-setup  dmeventd-client  gdm3.pid     irqbalance.pid  motd.dynamic   rebased        sshd.pid       udisks2

3.3.9 /media 和 /mnt 目录:外部设备的"访客接待处"

全称:media(媒体)、mount(挂载)

作用:这两个目录都是用来挂载外部文件系统的,但有不同的使用约定:

  • /media:现代桌面Linux系统使用的可移动媒体自动挂载点。当你插入U盘、光盘、移动硬盘时,系统会自动把它们挂载到/media目录下的一个子目录中(通常是/media/用户名/卷标)。这是FHS标准推荐的做法。

  • /mnt:传统的临时挂载点,供系统管理员手动挂载文件系统使用。当管理员需要临时挂载一个分区或网络共享时,通常会在/mnt下创建一个子目录(如/mnt/backup、/mnt/windows)作为挂载点。

类比理解

  • /media就像酒店的自动行李寄存柜。客人(U盘/光盘)来了,系统自动给他分配一个柜子,贴上标签。客人可以直接使用,不需要和前台打招呼。

  • /mnt就像酒店的临时会客室。当酒店员工(管理员)需要接待一些特殊的访客(手动挂载的分区)时,他们会临时安排一个房间。这些访客不是自助入住的,而是经过员工安排的。

查看/media和/mnt的命令

# 查看/media下是否有自动挂载的设备
ls /media/

# 如果有用户名子目录,继续查看
ls /media/username/

输出示例(插入U盘后):

MyUSBdrive
# 手动挂载一个分区到/mnt
sudo mkdir -p /mnt/mydisk
sudo mount /dev/sdb1 /mnt/mydisk
ls /mnt/mydisk

3.3.10 /opt 目录:第三方软件的"专属公寓"

全称:optional(可选的)

作用:/opt目录用于安装附加的(可选的)应用软件包,特别是那些不属于发行版自带软件的大型第三方商业软件。这些软件通常把所有文件(二进制、库、文档、配置)都放在/opt/软件名/目录下,形成一个独立的"小王国",不会和系统的其他部分混淆。

典型的/opt内容

  • /opt/google/chrome/:Google Chrome浏览器
  • /opt/vmware/:VMware虚拟化软件
  • /opt/sublime_text/:Sublime Text编辑器
  • /opt/lampp/:XAMPP集成环境

类比理解:/opt就像城市里的外籍人士公寓区。这些公寓区有自己的配套设施(超市、餐厅、学校),住在这里的外国人(第三方软件)可以形成一个相对独立的生活圈,不需要融入本地社区(系统目录),也不会干扰本地居民(系统自带软件)的生活。当你想"送走"某个外国人时,只需要拆除对应的公寓区即可,不会影响城市的其他部分。

查看/opt目录内容的命令

ls /opt

3.3.11 /srv 目录:网络服务的"货物仓库"

全称:services(服务)

作用:/srv目录存放的是本机提供的服务所对外提供的数据。比如:

  • Web服务器(Apache/Nginx)的网站内容可以放在/srv/www/
  • FTP服务器的共享文件可以放在/srv/ftp/
  • Git服务器的仓库可以放在/srv/git/

注意,很多发行版默认仍然把网站内容放在/var/www/,但FHS标准推荐使用/srv。你可以根据实际需求选择。

类比理解:/srv就像物流公司的发货仓库。这个仓库里存放的不是公司自用的办公用品(系统文件),也不是员工的私人物品(用户文件),而是准备发给客户的货物(对外提供服务的数据)。每个服务项目有自己的库区:快递区、冷链区、大件区等。


3.4 /bin、/sbin、/usr/bin、/usr/sbin、/usr/local/bin 的区别

在学习Linux的过程中,你会发现系统中有很多个存放"可执行程序"的目录:/bin、/sbin、/usr/bin、/usr/sbin、/usr/local/bin、/usr/local/sbin,甚至还有~/.local/bin等。对于初学者来说,这看起来非常混乱——为什么Linux不把程序都放在一个地方呢?为什么要有这么多bin目录?

这一节,我们就来彻底搞清楚这些目录的区别。理解它们不仅能帮助你更好地管理程序,还能让你明白Linux系统的设计哲学。

3.4.1 历史背景:从"小硬盘时代"说起

要理解这些目录的区别,我们需要先回到Unix和Linux的早期历史。

在20世纪70-80年代,计算机的硬盘非常小(几MB到几十MB),而Unix系统正在快速发展,系统程序和用户程序越来越多。当时的系统管理员面临一个问题:系统分区(根分区/)很快就被装满了。

为了解决这个问题,他们想出了一个办法:把不是系统启动必需的程序移到另一个硬盘或分区上。这样,即使那个分区坏了或者没挂载,系统至少还能启动到单用户模式进行修复。

于是,/usr目录诞生了。“usr"最初的意思是"user”(用户),但后来演变成了"Unix System Resources"(Unix系统资源)的含义。/usr用来存放那些不是系统启动和修复所必需的程序和数据。

类比理解:这就像是早期家庭的储物策略。以前家里只有一个大衣柜(根分区),但衣服越来越多放不下了。于是家里买了第二个衣柜(/usr分区),把换季的衣服和不常穿的衣服搬到第二个衣柜里。第一个衣柜只保留每天必需的衣物,这样即使第二个衣柜坏了,你至少还有衣服穿。

3.4.2 五个核心bin目录的区别

现在我们来看看这些bin目录各自的作用和存放内容的区别。

/bin(Basic User Binaries)

存放内容:系统启动和单用户模式下必需的基本用户命令。

关键特征

  • 这些命令在系统启动早期就需要可用。
  • 即使其他文件系统(如/usr)没有挂载,这些命令也必须能工作。
  • 所有用户都可以执行(普通用户和root)。

典型命令:ls、cp、mv、rm、cat、echo、mkdir、pwd、sh、mount、umount、chmod、df

类比理解:/bin就像野外求生包里的基础工具。无论你走到哪里(什么系统状态),这个包里的小刀、打火机、指南针、急救包都必须能用。它们是生存的最低保障。

/sbin(System Binaries)

存放内容:系统启动和系统修复所必需的基本系统管理命令。

关键特征

  • 这些命令用于系统管理、维护和网络配置。
  • 普通用户通常不需要执行这些命令。
  • 即使/usr没有挂载,这些命令也必须可用。

典型命令:fdisk、fsck、mkfs、reboot、halt、ifconfig、route、swapon、init

类比理解:/sbin就像汽车后备箱里的维修工具和备用零件。普通乘客不需要也不应该碰这些工具。只有司机或修车师傅(root)在紧急情况下才会用到它们。但这些工具必须随时在车里,因为万一在荒郊野外抛锚了,你不可能叫个快递送工具过来。

/usr/bin(User Binaries)

存放内容:系统正常运作时供普通用户使用的应用程序和命令。

关键特征

  • 这些命令不是系统启动所必需的。
  • 系统启动完成后,/usr通常已经挂载,这些命令就可以使用了。
  • 大多数用户日常使用的命令都在这里。

典型命令:gcc、make、python、vim、grep、awk、sed、find、wget、curl、ssh、scp、tar、gzip、man、less、more、top、ps、ping、netstat、firefox、libreoffice

类比理解:/usr/bin就像家里的日常用品柜。这里放着你的牙刷、毛巾、锅碗瓢盆、电视遥控器等。这些东西不是你野外求生必需的(没有它们你也能活着),但没有它们,你的日常生活质量会大幅下降。而且这些物品数量庞大、种类繁多,需要一个大柜子来存放。

/usr/sbin(User System Binaries)

存放内容:系统正常运作时供管理员使用的非关键系统管理命令。

关键特征

  • 这些命令用于系统管理,但不是启动和紧急修复所必需的。
  • 普通用户通常不需要使用。
  • 系统正常运行时,这些命令应该是可用的。

典型命令:useradd、userdel、groupadd、chroot、cron、inetd、sshd、ftpd、ntpd、dhcpd、named、apachectl、nginx、tcpdump、traceroute

类比理解:/usr/sbin就像物业管理处的工具间。这里有修水管的专业工具、电路检测仪、监控设备控制器等。普通住户不需要进这个房间。物业管理员(root)在日常工作中会使用这些工具,但这些工具不是"救命"级别的——如果真遇到大楼着火这种紧急情况,消防员会带自己的专业设备来,不会依赖物业的工具间。

/usr/local/bin(Local User Binaries)

存放内容:系统管理员手动编译安装的软件,或者发行版软件包管理器之外的第三方软件。

关键特征

  • 这些软件不是通过系统的包管理器(如apt、yum、dnf)安装的。
  • 通常由管理员从源代码编译安装,或者手动下载二进制包安装。
  • 这些软件优先于/usr/bin中的同名软件(如果PATH配置得当)。

典型内容:你自己编译安装的nginx、python新版本、node.js、自定义脚本等。

类比理解:/usr/local/bin就像你自己买的私人工具。比如,公司配了一把普通螺丝刀(/usr/bin里的工具),但你觉得不好用,自己花钱买了一把进口的高级螺丝刀(/usr/local/bin里的工具)。你的私人工具放在你自己的工具箱里,不属于公司财产(系统包管理器不管它们)。当你需要用螺丝刀时,你会优先用自己的那把(PATH中/usr/local/bin通常在/usr/bin前面)。

3.4.3 还有一个:/usr/local/sbin

与/usr/local/bin对应,/usr/local/sbin存放的是管理员手动安装的系统管理类程序。比如你自己编译安装了一个监控守护进程,它的管理命令可能就放在这里。

3.4.4 总结对比表

目录 存放内容 启动必需? 谁使用 安装方式
/bin 基本用户命令 所有用户 系统包管理器
/sbin 基本系统管理命令 root 系统包管理器
/usr/bin 普通应用程序 所有用户 系统包管理器
/usr/sbin 系统服务程序 root 系统包管理器
/usr/local/bin 手动安装的用户程序 所有用户 手动编译/安装
/usr/local/sbin 手动安装的系统程序 root 手动编译/安装

3.4.5 PATH环境变量:系统如何找到命令

当你在任何目录下输入一个命令(比如ls)时,系统是怎么知道去哪里找这个程序的呢?答案就是PATH环境变量

PATH是一个包含多个目录路径的列表,系统会按照这个列表的顺序逐个目录查找你输入的命令。

查看当前PATH

echo $PATH

输出示例:

/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/sbin:/home/username/.local/bin:/home/username/bin

注意这个顺序:系统会先查找/usr/local/bin,然后/usr/local/sbin,然后/usr/bin,然后/usr/sbin,然后/bin,然后/sbin,最后是你的个人bin目录。

这意味着:如果你在/usr/local/bin和/usr/bin中都放了一个名为python的程序,系统会优先执行/usr/local/bin中的那个!这就是为什么手动编译安装的软件可以"覆盖"系统自带软件的原因。

类比理解:PATH就像你找东西时的搜索顺序。假设你要找一把剪刀。你先在眼前的桌上找(当前目录),然后去客厅的抽屉找(PATH中的第一个目录),然后去卧室的抽屉找(PATH中的第二个目录),依此类推。剪刀放在哪个抽屉决定了你用到的到底是哪一把。

修改PATH的示例

# 临时修改(仅对当前终端会话有效)
export PATH="/my/custom/path:$PATH"

# 永久修改(添加到 ~/.bashrc 或 ~/.bash_profile)
echo 'export PATH="/my/custom/path:$PATH"' >> ~/.bashrc
source ~/.bashrc

3.4.6 现代系统的演变:合并趋势

值得注意的是,在现代的一些Linux发行版中(如Fedora、Arch Linux、部分版本的Ubuntu),/bin、/sbin、/lib、/lib64实际上是指向/usr/bin、/usr/sbin、/usr/lib、/usr/lib64的符号链接。这意味着根分区下的bin目录和/usr下的bin目录实际上是同一个地方。

这种变化的原因包括:

  1. 现代系统的启动机制(initramfs)可以在挂载根文件系统之前加载必要的驱动,所以/usr可以在系统启动早期就挂载。
  2. 统一路径简化了系统管理。
  3. 快照和回滚(在使用Btrfs等文件系统时)在统一目录结构下更容易实现。

但即便如此,理解这些目录的历史和用途仍然非常重要,因为很多文档、脚本和系统工具仍然遵循这些约定。

验证你的系统是否合并

# 查看 /bin 是否是符号链接
ls -ld /bin /sbin /lib /lib64

在合并的系统上,输出可能像这样:

lrwxrwxrwx 1 root root 7  1月 10 08:30 /bin -> usr/bin
lrwxrwxrwx 1 root root 7  1月 10 08:30 /sbin -> usr/sbin
lrwxrwxrwx 1 root root 7  1月 10 08:30 /lib -> usr/lib
lrwxrwxrwx 1 root root 9  1月 10 08:30 /lib64 -> usr/lib64

在传统的系统上,输出会是:

drwxr-xr-x  2 root root 4096  1月 10 08:30 /bin
drwxr-xr-x  2 root root 4096  1月 10 08:30 /sbin
drwxr-xr-x  2 root root 4096  1月 10 08:30 /lib
drwxr-xr-x  2 root root 4096  1月 10 08:30 /lib64

3.5 /etc 配置文件目录详解

3.5.1 /etc 目录的作用

全称:etcetera(等等,其他)—— 有趣的是,这个名字其实来源于早期Unix开发者的随性,它原意是"等等其他东西",但现在/etc已经成了Linux系统中最重要的目录之一。

作用:/etc目录存放的是系统级别的配置文件。所谓配置文件,就是告诉系统和各种程序"该怎么工作"的文本文件。几乎所有系统服务、网络设置、用户认证方式、启动参数等,都由/etc下的文件控制。

类比理解:/etc就像一栋大楼的物业管理手册和设备说明书合集。这本合集里包括:

  • 电梯的运行参数(最大载重、运行速度)—— 对应网络配置
  • 门禁系统的白名单—— 对应用户认证配置
  • 消防系统的联动方案—— 对应服务启动配置
  • 水电表的读数方式—— 对应系统环境变量
  • 保洁阿姨的工作时间表—— 对应定时任务配置

如果没有这些手册和说明书,大楼的每个设备就只能按照出厂默认设置运行,无法根据实际需求进行调整。

3.5.2 /etc 下的常见配置文件和目录

/etc下的文件非常多,这里我们按照功能分类介绍最重要的几个。

系统基础配置
文件/目录 说明
/etc/hostname 系统的主机名
/etc/hosts 本地主机名到IP地址的映射
/etc/resolv.conf DNS服务器配置
/etc/fstab 文件系统挂载表(开机自动挂载)
/etc/mtab 当前已挂载的文件系统列表
/etc/passwd 用户账户信息(用户名、UID、GID、家目录、shell)
/etc/shadow 用户密码的加密存储(只有root可读)
/etc/group 用户组信息
/etc/gshadow 组密码信息
/etc/shells 系统允许的登录shell列表
/etc/profile 全局环境变量和启动脚本
/etc/bashrc/etc/bash.bashrc 全局bash配置
/etc/environment 全局环境变量
/etc/localtime 本地时区设置(通常是符号链接)
/etc/timezone 时区名称
/etc/crontab 系统级定时任务配置
/etc/cron.*/ 定时任务的各个子目录
/etc/sysctl.conf/etc/sysctl.d/ 内核参数配置
/etc/udev/ 设备管理规则
/etc/modules/etc/modules-load.d/ 开机加载的内核模块
/etc/default/ 各种服务的默认参数
/etc/sysconfig//etc/default/ 系统和服务启动参数(发行版相关)
/etc/security/ 安全策略配置(PAM等)
/etc/pam.d/ 可插拔认证模块配置
/etc/ssh/ SSH服务配置
/etc/ssl/ SSL/TLS证书和配置
/etc/sudoers sudo权限配置
/etc/sudoers.d/ sudo权限配置子目录
网络配置
文件/目录 说明
/etc/network/ 网络接口配置(Debian/Ubuntu传统方式)
/etc/netplan/ Netplan网络配置(新版Ubuntu)
/etc/NetworkManager/ NetworkManager配置
/etc/sysconfig/network-scripts/ 网络脚本(RHEL/CentOS传统方式)
/etc/nsswitch.conf 名称服务切换配置(决定如何解析主机名、用户等)
/etc/services 网络服务端口号映射
/etc/protocols 网络协议号映射
服务配置
文件/目录 说明
/etc/systemd/ systemd系统和服务管理器的配置
/etc/init.d/ SysV init启动脚本(传统方式,已逐渐被systemd取代)
/etc/rc*.d/ 运行级别链接(传统方式)
/etc/logrotate.conf/etc/logrotate.d/ 日志轮转配置
/etc/rsyslog.conf/etc/syslog.conf 系统日志服务配置
/etc/nginx/ Nginx Web服务器配置
/etc/apache2//etc/httpd/ Apache Web服务器配置
/etc/mysql//etc/my.cnf MySQL/MariaDB数据库配置
/etc/postfix/ Postfix邮件服务器配置
/etc/dnsmasq.conf Dnsmasq DNS/DHCP服务配置

3.5.3 重要配置文件详解与示例

让我们深入看几个最常用、最重要的配置文件。

/etc/hostname —— 系统的"名字"

这个文件只包含一行:系统的主机名。

cat /etc/hostname

输出示例:

mylinux-server

修改主机名:

# 临时修改(立即生效,重启后丢失)
sudo hostname new-name

# 永久修改
sudo echo "new-name" > /etc/hostname

# 或者用 hostnamectl(systemd系统)
sudo hostnamectl set-hostname new-name
/etc/hosts —— 本地的"电话号码簿"

这个文件用于本地主机名到IP地址的映射。系统在查询DNS之前,会先查看这个文件。

cat /etc/hosts

输出示例:

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.100   fileserver.local    fileserver
192.168.1.101   webserver.local     webserver

类比理解:/etc/hosts就像你手机通讯录里的联系人。当你要打电话给"张三"时,你不需要去查114(DNS服务器),直接看手机通讯录就知道他的号码。而且通讯录里的号码可以覆盖真实号码——比如你把"张三"的号码改成了"110",那你打给"张三"就会打到110。/etc/hosts的优先级高于DNS,常被用于本地测试或屏蔽广告网站。

/etc/passwd —— 用户账户的"花名册"

这个文件包含了系统上所有用户的基本信息。虽然名字里有"passwd",但现代Linux中密码并不存储在这里(而是存储在/etc/shadow中)。

cat /etc/passwd

输出示例:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
username:x:1000:1000:User Name:/home/username:/bin/bash

每一行代表一个用户,用冒号分隔成7个字段:

用户名:密码占位符:用户ID(UID):组ID(GID):注释/全名:家目录:登录Shell
字段 说明 示例
1 用户名 root、username
2 密码占位符 x(表示密码在/etc/shadow中)
3 用户ID(UID) 0是root,1-999是系统用户,1000+是普通用户
4 组ID(GID) 主组的ID
5 注释/全名 root、User Name
6 家目录 /root、/home/username
7 登录Shell /bin/bash、/sbin/nologin

类比理解:/etc/passwd就像公司的员工花名册。上面记录了每个员工的工号(UID)、部门(GID)、办公座位(家目录)、联系方式(Shell)。花名册是公开的,所有员工都能看到。但员工的工资卡密码不会写在花名册上,而是存在财务室的保险柜里(/etc/shadow)。

/etc/shadow —— 密码的"保险柜"

这个文件存储了用户的加密密码和密码策略信息。只有root用户才能读取。

sudo cat /etc/shadow

输出示例:

root:$6$rounds=5000$saltsalt$encryptedpasswordhash:19000:0:99999:7:::
username:$6$rounds=5000$abcdefgh$anotherencryptedhash:19000:0:99999:7:::

每一行同样用冒号分隔,包含9个字段:

字段 说明
1 用户名
2 加密后的密码
3 上次修改密码的日期(自1970年1月1日以来的天数)
4 密码修改后最短多少天才能再次修改
5 密码多少天后必须修改
6 密码过期前多少天开始警告
7 密码过期后多少天账户被禁用
8 账户被禁用的日期
9 保留字段
/etc/fstab —— 开机挂载的"日程表"

这个文件定义了系统启动时自动挂载哪些文件系统。我们将在3.10节中详细讲解它,这里先看一个示例。

cat /etc/fstab

输出示例:

#
# /etc/fstab
# Created by anaconda on Mon Jan 10 08:30:00 2024
#
UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   /           ext4    defaults        1 1
UUID=yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy   /boot       ext4    defaults        1 2
UUID=zzzz-zzzz                              /boot/efi   vfat    umask=0077,shortname=winnt 0 2
/dev/mapper/centos-swap                     none        swap    defaults        0 0
/etc/profile 和 ~/.bashrc —— 环境变量的"初始化脚本"

这些文件用于设置用户的环境变量和启动时执行的命令。

  • /etc/profile:全局配置文件,所有用户登录时都会执行。
  • ~/.bashrc:个人配置文件,每个用户自己的bash配置。
# 查看 /etc/profile 的部分内容
head -30 /etc/profile

输出示例:

# /etc/profile

# System wide environment and startup programs, for login setup
# Functions and aliases go in /etc/bashrc

# It's NOT a good idea to change this file unless you know what you
# are doing. It's much better to create a custom.sh shell script in
# /etc/profile.d/ to make custom changes to your environment, as this
# will prevent the need for merging in future updates.

pathmunge () {
    case ":${PATH}:" in
        *:"$1":*)
            ;;
        *)
            if [ "$2" = "after" ] ; then
                PATH=$PATH:$1
            else
                PATH=$1:$PATH
            fi
    esac
}
/etc/crontab —— 定时任务的"闹钟设置"

这个文件用于设置系统级的定时任务,指定在特定时间执行特定命令。

cat /etc/crontab

输出示例:

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# |  .------------- hour (0 - 23)
# |  |  .---------- day of month (1 - 31)
# |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...
# |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# |  |  |  |  |
# *  *  *  *  * user-name  command to be executed
/etc/ssh/sshd_config —— SSH服务的"门禁规则"

这个文件控制SSH远程登录服务的行为。

sudo cat /etc/ssh/sshd_config | grep -v "^#" | grep -v "^$"

输出示例(部分):

HostKey /etc/ssh/ssh_host_rsa_key
HostKey /etc/ssh/ssh_host_ecdsa_key
HostKey /etc/ssh/ssh_host_ed25519_key
SyslogFacility AUTHPRIV
PermitRootLogin yes
PasswordAuthentication yes
ChallengeResponseAuthentication no
GSSAPIAuthentication yes
GSSAPICleanupCredentials no
UsePAM yes
X11Forwarding yes
AcceptEnv LANG LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES
AcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT
AcceptEnv LC_IDENTIFICATION LC_ALL LANGUAGE
AcceptEnv XMODIFIERS
Subsystem	sftp	/usr/libexec/openssh/sftp-server

3.5.4 /etc 目录的备份建议

/etc目录至关重要,一旦配置错误可能导致系统无法启动或服务异常。因此,定期备份/etc是系统管理的基本要求。

备份建议

  1. 修改前备份单个文件

    sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup.$(date +%Y%m%d)
    
  2. 定期完整备份/etc

    # 使用tar打包备份
    sudo tar -czvf /backup/etc-backup-$(date +%Y%m%d).tar.gz /etc
    
    # 或者使用rsync同步到远程
    sudo rsync -avz /etc/ user@backup-server:/backups/myserver/etc/
    
  3. 使用版本控制(高级)

    # 把/etc纳入Git版本控制
    cd /etc
    sudo git init
    sudo git add .
    sudo git commit -m "Initial /etc backup"
    
    # 每次修改后提交
    sudo git add ssh/sshd_config
    sudo git commit -m "Updated SSH config"
    
  4. 修改配置前先查看文档

    • 大多数配置文件都有详细的注释说明。
    • 使用man 5 配置文件名查看帮助(如man 5 sshd_config)。

类比理解:备份/etc就像复印重要的合同文件。你在修改合同条款之前,应该先把原合同复印一份存档。万一修改后出了问题,你可以拿出复印件恢复原状。对于/etc这样的核心配置,"先备份,后修改"应该成为你的铁律。


3.6 /var、/tmp、/home 目录用途

3.6.1 /var 目录:系统的"动态档案室"

全称:variable(可变的)

作用:/var目录存放的是在系统运行过程中会不断变化的数据。与/usr不同(/usr在正常运行下应该是静态的,只读或很少修改),/var中的数据在系统运行时会频繁地被创建、修改、删除。

类比理解:/var就像医院的病历档案室和运营数据室。这里存放着:

  • 每天的就诊记录(日志文件)
  • 排队等候的患者名单(任务队列)
  • 医生和护士的值班表(运行时数据)
  • 药品库存变化记录(缓存数据)
  • 患者信箱里的信件(邮件)

这些数据每天都在变化,是医院"运营"产生的数据,而不是医院"建筑"本身的一部分。

/var 的子目录详解
子目录 说明
/var/log/ 系统和应用程序的日志文件
/var/spool/ 任务队列(邮件队列、打印队列、cron任务等)
/var/mail/ 用户邮箱(传统位置,现在常链接到/var/spool/mail/)
/var/cache/ 应用程序缓存数据
/var/lib/ 应用程序的状态信息和持久化数据
/var/tmp/ 重启后仍然保留的临时文件
/var/run/ 运行时数据(已迁移到/run,通常是符号链接)
/var/lock/ 锁文件(已迁移到/run/lock,通常是符号链接)
/var/crash/ 系统崩溃转储文件
/var/opt/ /opt下软件的可变数据
/var/local/ /usr/local下软件的可变数据
/var/www/ Web服务器内容(传统位置,部分发行版使用)
/var/ftp/ FTP服务器共享文件(传统位置)
/var/log/ —— 系统的"黑匣子"

这是/var中最重要的子目录,存放着系统和各种服务的日志文件。日志是排查系统问题的关键依据。

常见的日志文件

日志文件 说明
/var/log/messages/var/log/syslog 系统通用日志
/var/log/secure/var/log/auth.log 认证和安全相关日志
/var/log/kern.log 内核日志
/var/log/dmesg 启动时的内核环缓冲区消息
/var/log/boot.log 启动过程日志
/var/log/cron cron定时任务日志
/var/log/maillog/var/log/mail.log 邮件服务日志
/var/log/httpd//var/log/nginx/ Web服务器日志
/var/log/yum.log/var/log/dpkg.log 软件包管理日志
/var/log/wtmp 登录历史记录(二进制文件,用last查看)
/var/log/btmp 失败的登录尝试(二进制文件,用lastb查看)
/var/log/lastlog 每个用户最后一次登录时间(二进制文件)

查看日志的常用命令

# 实时查看系统日志(systemd系统)
sudo journalctl -f

# 查看最近的100行系统日志
sudo journalctl -n 100

# 查看某个服务的日志
sudo journalctl -u sshd

# 查看传统的messages日志
cat /var/log/messages

# 查看认证日志
cat /var/log/secure

# 查看登录历史
last

# 查看失败的登录尝试
sudo lastb

# 搜索日志中的关键词
grep "error" /var/log/messages

日志文件内容示例

cat /var/log/secure | tail -10

输出示例:

Jul 27 08:15:01 server sshd[1234]: Accepted password for username from 192.168.1.50 port 54321 ssh2
Jul 27 08:15:01 server sshd[1234]: pam_unix(sshd:session): session opened for user username(uid=1000) by (uid=0)
Jul 27 09:30:22 server sudo: username : TTY=pts/0 ; PWD=/home/username ; USER=root ; COMMAND=/bin/cat /etc/shadow
Jul 27 10:00:00 server sshd[5678]: Failed password for invalid user hacker from 203.0.113.45 port 12345 ssh2
Jul 27 10:00:03 server sshd[5678]: Failed password for invalid user hacker from 203.0.113.45 port 12345 ssh2
Jul 27 10:00:05 server sshd[5678]: Connection closed by invalid user hacker 203.0.113.45 port 12345 [preauth]
/var/spool/ —— 任务的"等候大厅"

spool原意是"线轴",在计算机领域指"排队等待处理的数据"。/var/spool存放各种队列数据。

ls /var/spool/

输出示例:

anacron  at  cron  lpd  mail  postfix  rsyslog
  • /var/spool/mail/:用户的 incoming 邮件。
  • /var/spool/cron/:用户的 cron 任务。
  • /var/spool/lpd//var/spool/cups/:打印任务队列。
  • /var/spool/postfix/:Postfix邮件服务器的邮件队列。

类比理解:/var/spool就像银行大厅的取号排队系统。每个客户(任务)来了先取一个号,坐在等候区等待叫号。窗口(服务程序)按照号码顺序逐个处理。如果某个窗口坏了,排队的人不会消失,等窗口修好后继续处理。

/var/lib/ —— 程序的"私人储物柜"

/var/lib存放的是应用程序在运行过程中需要持久保存的数据,但这些数据又不是用户直接操作的文件。

ls /var/lib/

输出示例(部分):

alternatives  dnf  initramfs  logrotate  machines  misc  NetworkManager  os-prober  plymouth  polkit-1  rpm  rpm-state  rsyslog  selinux  systemd  uploader  yum
  • /var/lib/mysql/:MySQL数据库的数据文件。
  • /var/lib/dpkg/(Debian/Ubuntu)或 /var/lib/rpm/(RHEL/CentOS):软件包数据库。
  • /var/lib/systemd/:systemd的持久化状态。
  • /var/lib/machines/:systemd-nspawn容器。

类比理解:/var/lib就像健身房会员的私人储物柜。每个会员(应用程序)有一个带锁的柜子,存放自己的私人物品(状态数据)。其他会员不能打开你的柜子,健身房管理员(系统)也不会随意清理里面的东西。

3.6.2 /tmp 目录:系统的"临时便签纸"

全称:temporary(临时的)

作用:/tmp目录用于存放临时文件。任何用户和程序都可以在这里创建临时文件。/tmp目录通常是全世界可写的(权限为1777,即rwxrwxrwt,带sticky bit)。

关键特性

  1. 全局可写:所有用户和程序都可以在/tmp下创建文件。
  2. Sticky Bit保护:/tmp的权限通常是drwxrwxrwt。最后的t就是sticky bit,它确保用户只能删除自己创建的文件,不能删除其他用户的文件。这防止了恶意用户删除别人的临时文件。
  3. 重启清空:传统上,/tmp中的文件在系统重启后会被清空。在现代systemd系统上,/tmp可能被挂载为tmpfs(内存文件系统),这意味着不仅重启后清空,而且数据实际上存放在内存中,速度极快。
  4. 定期清理:一些系统会配置定时任务(如systemd-tmpfiles或tmpwatch)来定期删除/tmp中长时间未访问的文件。

类比理解:/tmp就像会议室里的白板或便利贴墙。任何人都可以上去写东西、贴便签,方便大家临时记录和交换信息。每天下班(系统重启)或定期,保洁阿姨会把白板擦干净、把便签收走。你不能指望白板上的内容明天还在,它只是给当下使用的。

查看/tmp目录的权限和特性

ls -ld /tmp

输出示例:

drwxrwxrwt 15 root root 4096 7月  27 14:30 /tmp

注意:drwxrwxrwt中的t就是sticky bit。

使用/tmp的示例

# 在/tmp中创建临时文件
cd /tmp
touch my_temp_file.txt
echo "This is temporary data" > my_temp_file.txt

# 查看文件
ls -l my_temp_file.txt

输出示例:

-rw-r--r-- 1 username username 23 7月  27 14:35 my_temp_file.txt

重要的安全提示

由于/tmp是全局可写的,它有时会被恶意程序利用。因此:

  • 不要在/tmp中存放敏感信息(密码、私钥等)。
  • 程序在/tmp中创建临时文件时,应该使用随机文件名(如mktemp命令生成的),避免文件名冲突和被预测。
  • 一些安全敏感的系统会把/tmp挂载为noexec(禁止执行)、nosuid(禁止SUID)等选项。

安全创建临时文件的方法

# 使用 mktemp 创建安全的临时文件
TMPFILE=$(mktemp /tmp/myscript.XXXXXX)
echo "Data" > "$TMPFILE"
cat "$TMPFILE"
rm -f "$TMPFILE"

# 创建临时目录
TMPDIR=$(mktemp -d /tmp/mydir.XXXXXX)
touch "$TMPDIR/file1"
rm -rf "$TMPDIR"

3.6.3 /home 目录:用户的"私人领地"

作用:/home目录存放的是普通用户的个人数据和配置文件。每个普通用户在/home下都有一个以自己用户名命名的子目录,称为"家目录"(Home Directory)或"主目录"。

类比理解:/home就像公寓大楼的各个住户房间。大楼的公共区域(/bin、/etc、/usr等)由物业统一管理,每个住户不能随意改动。但每个住户自己的房间(/home/用户名)是私人空间,住户可以在里面自由布置、存放私人物品。住户之间不能随便进入别人的房间(权限控制),物业(root)虽然有万能钥匙可以进入,但通常尊重住户隐私。

/home 的结构
ls -la /home/

输出示例:

drwxr-xr-x  5 root     root     4096 7月  27 10:00 .
drwxr-xr-x 18 root     root     4096 7月  27 10:00 ..
drwx------ 18 alice    alice    4096 7月  27 12:00 alice
drwx------ 20 bob      bob      4096 7月  27 11:30 bob
drwx------ 15 charlie  charlie  4096 7月  27 13:00 charlie
用户家目录中的常见内容

进入某个用户的家目录,你会看到以下内容:

ls -la /home/username/

输出示例:

drwx------ 18 username username 4096 7月  27 14:00 .
drwxr-xr-x  5 root     root     4096 7月  27 10:00 ..
-rw-------  1 username username  567 7月  27 14:00 .bash_history
-rw-r--r--  1 username username  220 1月  10 08:30 .bash_logout
-rw-r--r--  1 username username 3771 1月  10 08:30 .bashrc
drwx------ 12 username username 4096 7月  27 13:00 .cache
drwx------ 14 username username 4096 7月  27 13:00 .config
drwx------  3 username username 4096 1月  10 08:30 .local
-rw-r--r--  1 username username  807 1月  10 08:30 .profile
drwxr-xr-x  2 username username 4096 1月  10 08:30 Desktop
drwxr-xr-x  2 username username 4096 1月  10 08:30 Documents
drwxr-xr-x  2 username username 4096 1月  10 08:30 Downloads
drwxr-xr-x  2 username username 4096 1月  10 08:30 Music
drwxr-xr-x  2 username username 4096 1月  10 08:30 Pictures
drwxr-xr-x  2 username username 4096 1月  10 08:30 Public
drwxr-xr-x  2 username username 4096 1月  10 08:30 Videos

家目录中的常见文件和目录

文件/目录 说明
.bashrc Bash shell的配置文件,每次打开新终端时执行
.bash_profile.profile 登录时执行的配置文件
.bash_history 你输入过的命令历史
.bash_logout 退出登录时执行的脚本
.ssh/ SSH密钥和配置
.config/ 现代应用程序的配置目录(XDG标准)
.cache/ 应用程序缓存
.local/ 本地安装的程序和数据
Desktop/ 桌面文件
Documents/ 文档
Downloads/ 下载
Music/ 音乐
Pictures/ 图片
Videos/ 视频
Public/ 公共共享文件

root用户的家目录:root用户的家目录不在/home下,而是单独的/root目录。这是为了安全考虑——即使/home分区出现问题或无法挂载,root仍然有自己的工作空间。

切换到家目录

# 使用 cd 不加参数,直接回到家目录
cd
pwd

输出示例:

/home/username
# 或者使用 ~
cd ~
pwd

类比理解:用户的家目录就像你自己的卧室。卧室里有你的床(个人文件)、衣柜(Documents、Pictures等)、书桌(Desktop)、书桌抽屉里的文具(.bashrc等配置文件)。你每天都会回到卧室(cd ~),在这里你感到最自在,有最大的自由。卧室的钥匙只有你和管理员有,其他住户不能随意进入。


3.7 绝对路径与相对路径

在Linux(以及所有类Unix系统)中,定位一个文件或目录的位置有两种方式:绝对路径相对路径。理解这两种路径的区别,并熟练使用它们,是你在Linux中游刃有余地导航文件系统的基础。很多初学者在命令行中迷失方向,往往就是因为没有真正理解路径的概念。

3.7.1 绝对路径:从"城市大门"开始的完整地址

**绝对路径(Absolute Path)**是从根目录/开始的完整路径,它精确地描述了从文件系统树根到目标文件或目录的完整路线。无论你现在身处哪个目录,绝对路径指向的位置都是唯一不变的。

绝对路径的特征

  • 总是以/开头。
  • 不受当前工作目录的影响。
  • 可以唯一确定文件系统中的一个位置。

生活中的类比:绝对路径就像完整的邮政地址。比如"中华人民共和国北京市海淀区中关村大街1号科技大厦10层1001室"。无论邮递员现在在哪里——在上海、在广州、还是在同一条大街的另一栋楼——这个地址都能唯一地指向那个房间。它从国家(根/)开始,经过省、市、区、街道、门牌号、楼层、房间号,一层层精确到位。

Linux中的绝对路径示例

/etc/ssh/sshd_config
/home/username/Documents/report.docx
/usr/bin/python3
/var/log/syslog
/tmp/my_temp_file.txt

这些路径都以/开头,无论你当前在哪个目录下,它们指向的文件都是确定不变的。

使用绝对路径的实战示例

# 无论你在哪个目录,以下命令都指向同一个文件
cat /etc/passwd

# 复制文件时使用绝对路径
cp /home/alice/Documents/photo.jpg /home/bob/Pictures/

# 编辑配置文件时使用绝对路径
sudo vim /etc/ssh/sshd_config

# 查看某个程序的绝对路径
which python3

输出示例:

/usr/bin/python3

which命令告诉你,当你输入python3时,系统实际执行的是/usr/bin/python3这个绝对路径指向的程序。

3.7.2 相对路径:从"当前位置"出发的局部指引

**相对路径(Relative Path)是相对于当前工作目录(Current Working Directory)**的路径。它不从根目录开始,而是从你现在所在的位置出发,描述如何到达目标文件或目录。

相对路径的特征

  • 不以/开头(以/开头的就是绝对路径)。
  • 依赖于当前工作目录。
  • 同一个相对路径,在不同的当前目录下,可能指向完全不同的位置。

生活中的类比:相对路径就像你问路人"洗手间在哪里"时的回答。假设你在商场三楼,路人告诉你"往前走20米,右转就到了"。这个指引是相对于你当前的位置(三楼某处)的。如果你在商场一楼问同样的问题,得到的答案可能是"坐电梯到三楼,往前走20米,右转"。"往前走20米,右转"这个相对路径,在三楼是正确的,在一楼就完全不适用。

Linux中的相对路径示例

假设你当前在/home/username目录下:

相对路径 实际指向的绝对路径
Documents /home/username/Documents
Documents/report.docx /home/username/Documents/report.docx
../bob /home/bob
./.bashrc /home/username/.bashrc
../../etc/passwd /etc/passwd

如果你当前在/var/log目录下:

相对路径 实际指向的绝对路径
messages /var/log/messages
../spool/mail /var/spool/mail
../../etc/hosts /etc/hosts

注意,同样的相对路径../spool/mail,在/var/log下指向/var/spool/mail,但如果在/home/username下使用,就会指向/home/spool/mail(如果存在的话)。这就是相对路径的"相对性"。

查看当前工作目录

pwd

输出示例:

/home/username/Documents

3.7.3 特殊目录符号:. 和 …

在相对路径中,有两个极其重要的特殊符号:

.(点):当前目录

.代表当前目录。它就像你说"就在这里"。

使用场景

  1. 执行当前目录下的程序

    # 假设你写了一个脚本 myscript.sh,想要执行它
    ./myscript.sh
    

    为什么需要./?因为出于安全考虑,Linux的PATH环境变量通常不包含当前目录(.)。如果你直接输入myscript.sh,系统会到PATH指定的目录中去找,而不会在当期目录找。加上./就是明确告诉系统"执行当前目录下的myscript.sh"。

  2. 复制文件到当前目录

    cp /etc/hosts .
    

    这个命令把/etc/hosts复制到当前目录下。.在这里就代表"当前目录这个目的地"。

  3. 在命令中明确指定当前目录

    ls .
    

    这和直接输入ls效果一样,都是列出当前目录的内容。但在某些复杂的命令中,.可以明确表示"从这里开始"。

类比理解.就像你脚下的这片土地。无论你站在哪里,“这里"就是你当前的位置。你说"把东西放在这里”,大家就知道是放在你站的地方。

..(两个点):父目录

..代表父目录,也就是当前目录的上一级目录。

使用场景

  1. 返回上一级目录

    cd ..
    

    这是Linux中最常用的命令之一。无论你当前在哪个目录,cd ..都会带你回到上一级。

  2. 访问上一级目录中的文件

    # 当前在 /home/username/Documents
    cat ../.bashrc
    # 实际访问的是 /home/username/.bashrc
    
  3. 向上多级跳转

    cd ../..    # 向上两级
    

cd …/…/… # 向上三级


4. **结合子目录使用**:
```bash
# 当前在 /home/username/Documents
ls ../Pictures
# 列出 /home/username/Pictures 的内容

类比理解..就像**“上楼"或"回小区大门”**。假设你在某栋楼的10层1001室(当前目录),..就是10层的走廊(父目录/1001的上级),../..就是这栋楼的大堂(向上两级),../../..就是小区大门(向上三级)。你可以说"我去楼上邻居家借点东西"(../neighbor),或者说"我去大堂的物业办公室"(../..)。

3.7.4 更多特殊路径符号

除了...,Linux中还有一些常用的路径快捷符号:

~(波浪号):用户的家目录

~代表当前用户的家目录。这是你在Linux中最温暖的"避风港"。

# 切换到当前用户的家目录
cd ~

# 列出当前用户家目录的内容
ls ~

# 访问家目录下的某个文件
cat ~/.bashrc

# 复制文件到家目录
cp document.txt ~/

~用户名:指定某个用户的家目录

# 访问用户 alice 的家目录(需要相应权限)
ls ~alice

# 复制文件到 alice 的桌面
cp notice.txt ~alice/Desktop/

类比理解~就像你的家庭住址的快捷拨号。你不需要每次都报出完整的"中华人民共和国北京市海淀区某某街道某某小区X号楼X单元XXX室",只需要说"我家",大家就知道是哪里。而~alice就像"Alice家",你一提到这个名字,大家就知道去哪个地址。

-(短横线):上一次所在的目录

cd -命令可以让你快速在两个目录之间来回切换。它把你带到上一次所在的目录

# 假设你当前在 /var/log
cd /etc/ssh
pwd
# 输出:/etc/ssh

# 快速回到刚才的目录
cd -
pwd
# 输出:/var/log

# 再按一次,又回到 /etc/ssh
cd -
pwd
# 输出:/etc/ssh

类比理解cd -就像电视遥控器的"返回"按钮导航软件的"回到上一地点"。你在地图上从A点导航到了B点,按一下"返回"就回到了A点,再按一下又回到了B点。这对于在两个目录之间频繁切换的工作场景极其有用,比如一边在/var/log中查看日志,一边在/etc中修改配置。

3.7.5 绝对路径 vs 相对路径:如何选择?

在实际使用中,你应该根据场景选择合适的路径表示方式:

使用绝对路径的场景

  1. 编写脚本:脚本可能在任何目录下运行,使用绝对路径可以确保找到正确的文件。
  2. 配置文件:配置文件中的路径通常使用绝对路径,因为配置和当前目录无关。
  3. 系统管理操作:修改系统文件、启动服务等,使用绝对路径更清晰、更安全。
  4. 初次导航到某个位置:当你要去一个很远的地方时,用绝对路径一步到位。

使用相对路径的场景

  1. 在当前目录附近操作:比如当前在/home/username/project/src,要访问同目录下的main.c或子目录include/header.h,用相对路径更简洁。
  2. 批量处理同级文件:比如在某个项目目录下编译所有.c文件。
  3. 保持命令的通用性:相对路径使得命令在不同环境下(如不同用户的home目录)都能工作。

类比理解

  • 绝对路径就像用GPS导航输入完整地址。无论你在哪里,输入"北京市天安门广场"都能准确导航到目的地。适合长途出行、不熟悉路况、需要精确到达的场景。
  • 相对路径就像在小区里问路。你已经在这个小区了,只需要知道"往前走两个路口右转"。适合短距离移动、熟悉环境、快速方便的场景。

3.7.6 实战练习:路径切换大挑战

让我们通过一系列实战操作来巩固路径的概念。

场景设置:假设你的系统有以下目录结构:

/
├── etc
│   ├── hosts
│   ├── passwd
│   └── ssh
│       └── sshd_config
├── home
│   ├── alice
│   │   ├── Documents
│   │   │   └── report.txt
│   │   └── Pictures
│   │       └── cat.jpg
│   └── bob
│       └── Downloads
│           └── game.zip
├── tmp
│   └── temp.txt
└── var
    └── log
        └── syslog

练习1:使用绝对路径查看文件

# 1. 查看 /etc/hosts 的内容(使用绝对路径)
cat /etc/hosts

# 2. 查看 alice 的 report.txt(使用绝对路径)
cat /home/alice/Documents/report.txt

# 3. 查看系统日志(使用绝对路径)
cat /var/log/syslog

练习2:切换目录并使用相对路径

# 假设你当前在 /home/alice

# 1. 进入 Documents 目录(相对路径)
cd Documents
pwd
# 输出:/home/alice/Documents

# 2. 查看当前目录下的 report.txt
cat report.txt

# 3. 进入 Pictures 目录(相对路径,需要先返回上一级)
cd ../Pictures
pwd
# 输出:/home/alice/Pictures

# 4. 查看 Pictures 下的 cat.jpg
ls cat.jpg

# 5. 切换到 bob 的 Downloads 目录(相对路径)
cd ../../bob/Downloads
pwd
# 输出:/home/bob/Downloads

# 6. 查看 game.zip
ls game.zip

练习3:使用特殊符号快速导航

# 1. 先进入 /etc/ssh
cd /etc/ssh
pwd
# 输出:/etc/ssh

# 2. 快速回到家目录
cd ~
pwd
# 输出:/home/username(假设当前用户是username)

# 3. 回到 /etc/ssh
cd -
pwd
# 输出:/etc/ssh

# 4. 查看家目录下的 .bashrc
cat ~/.bashrc

# 5. 复制 /etc/hosts 到当前目录(家目录)
cp /etc/hosts .
ls hosts

练习4:混合使用绝对路径和相对路径

# 1. 进入 /tmp
cd /tmp

# 2. 使用相对路径查看上一级目录的内容
ls ..

# 3. 使用相对路径查看 /etc 下的 passwd(从 /tmp 出发)
cat ../etc/passwd

# 4. 使用绝对路径做同样的事情
cat /etc/passwd

# 5. 创建一个子目录并进入
mkdir mydir
cd mydir
pwd
# 输出:/tmp/mydir

# 6. 使用相对路径返回 /tmp
cd ..
pwd
# 输出:/tmp

# 7. 连续向上返回两级
cd ../..
pwd
# 输出:/(根目录)

常见错误和注意事项

  1. 混淆绝对路径和相对路径

    # 错误:如果你想访问当前目录下的某个文件,不应该以 / 开头
    cat /myfile.txt    # 这会去根目录下找 myfile.txt!
    cat myfile.txt     # 这才是当前目录下的 myfile.txt
    
  2. cd命令后面不要加文件

    # 错误:cd只能进入目录,不能进入文件
    cd /etc/passwd     # 报错:不是目录
    
    # 正确:只进入目录部分
    cd /etc
    
  3. 权限问题

    # 即使路径写对了,没有权限也会失败
    cd /root           # 普通用户通常会收到"Permission denied"
    cat /etc/shadow    # 普通用户无权读取
    
  4. 路径中的空格

    # 如果目录名或文件名中有空格,需要用引号或反斜杠转义
    cd My\ Documents
    # 或者
    cd "My Documents"
    

3.8 文件类型与文件属性

当你使用ls -l命令列出文件时,你会看到一长串看起来神秘的字符。对于零基础的小白来说,这些字符就像天书一样。但这一节学完后,你将能一眼"读懂"任何一个文件的"身份档案"。

3.8.1 Linux的七种文件类型

在Linux中,"一切皆文件"这句话不是随便说说的。Linux把所有东西都抽象为文件,并且定义了七种文件类型。你可以用ls -l命令的第一列字符来识别文件类型。

文件类型 ls -l中的标识 说明 生活中的类比
普通文件 - 存储数据的最常见文件类型,如文本文件、图片、程序等 书本:有封面有内容,是最常见的物品
目录 d 包含其他文件和目录的容器 文件夹:用来整理和存放文件
符号链接(软链接) l 指向另一个文件或目录的快捷方式 快捷方式/路标:指向真正的地方
块设备 b 按块读写数据的设备,如硬盘、分区 蓄水池:可以一桶一桶地取水
字符设备 c 按字符流读写数据的设备,如终端、串口 水龙头:水是一滴滴流出来的
命名管道 p 进程间通信机制(FIFO) 传声筒:连接两个人,声音直接传递
套接字 s 进程间或网络通信的端点 电话插座:插上去就能通话

让我们详细理解每一种类型。

1. 普通文件(Regular File)-

普通文件是Linux中最常见的文件类型。它们用来存储数据——可以是文本、图片、音频、视频、程序代码、压缩包,或者任何二进制数据。

普通文件本身不区分"这是文本文件"还是"这是可执行程序"(Windows用扩展名.exe.txt等来区分)。在Linux中,一个文件是否是可执行的,取决于它的权限位(后面会讲),而不是文件名。

创建普通文件

# 创建空文件
touch myfile.txt

# 写入内容
echo "Hello Linux" > hello.txt

# 复制文件
cp hello.txt hello2.txt

查看文件类型

ls -l hello.txt

输出示例:

-rw-r--r-- 1 username username 12 7月  27 15:00 hello.txt

注意最左边的-,这就是普通文件的标识。

2. 目录(Directory)d

目录是文件的容器,它可以包含其他文件和子目录,形成树形结构。

创建目录

mkdir mydir
ls -ld mydir

输出示例:

drwxr-xr-x 2 username username 4096 7月  27 15:05 mydir

最左边的d表示这是一个目录。

重要提示:在Linux中,目录也是一种"文件"——它是一种特殊的文件,存储的是该目录下所有文件和子目录的列表(你可以理解为"目录的内容就是一张清单")。

类比理解:目录就像文件夹抽屉。文件夹本身不是你要阅读的内容,但它里面装着很多纸张(文件)。文件夹还可以套文件夹(目录嵌套),形成层级收纳系统。

3. 符号链接/软链接(Symbolic Link)l

符号链接(也叫软链接)是指向另一个文件或目录的"快捷方式"。它本身不存储实际数据,只存储目标的路径。

创建符号链接

# 创建一个指向 hello.txt 的软链接
ln -s hello.txt mylink

# 查看
ls -l mylink

输出示例:

lrwxrwxrwx 1 username username 9 7月  27 15:10 mylink -> hello.txt

最左边的l表示这是一个符号链接。箭头->后面是它指向的目标。

类比理解:符号链接就像路标或指示牌。你在高速公路上看到一个指示牌"前方500米:服务区"。指示牌本身不是服务区,但它告诉你服务区在哪里。如果服务区被拆除了(目标文件被删除),指示牌还在,但指向了一个不存在的地方(这叫做" dangling link",悬空链接)。

我们将在3.9节详细讲解硬链接和软链接的区别。

4. 块设备(Block Device)b

块设备是以固定大小的"块"(通常是512字节或4096字节)为单位进行数据传输的设备。硬盘、SSD、分区、光驱等都是块设备。

ls -l /dev/sda

输出示例:

brw-rw---- 1 root disk 8, 0 7月  27 10:15 /dev/sda

最左边的b表示这是一个块设备。

类比理解:块设备就像蓄水池或油罐。你不会一滴一滴地取水,而是用水桶(块)一桶一桶地取。每次操作的数据量都是固定的"一桶"。

5. 字符设备(Character Device)c

字符设备是以字符流(逐个字符或字节)的方式传输数据的设备。终端、键盘、鼠标、串口、/dev/null、/dev/random等都是字符设备。

ls -l /dev/tty0
ls -l /dev/null
ls -l /dev/random

输出示例:

crw--w---- 1 root tty  4, 0 7月  27 10:15 /dev/tty0
crw-rw-rw- 1 root root 1, 3 7月  27 10:15 /dev/null
crw-rw-rw- 1 root root 1, 8 7月  27 10:15 /dev/random

最左边的c表示字符设备。

类比理解:字符设备就像水龙头或输液管。水是一滴一滴(或一小股一小股)连续不断地流出来的,而不是一桶一桶的。

6. 命名管道(Named Pipe / FIFO)p

命名管道是一种特殊的文件,用于在两个进程之间传递数据。一个进程往管道里写数据,另一个进程从管道里读数据。命名管道在文件系统中有一个实际的路径名(这就是"命名"的含义),与之相对的是"匿名管道"。

创建命名管道

mkfifo mypipe
ls -l mypipe

输出示例:

prw-r--r-- 1 username username 0 7月  27 15:20 mypipe

最左边的p表示命名管道。

使用命名管道

# 终端1:往管道里写数据
echo "Hello from pipe" > mypipe

# 终端2:从管道里读数据
cat mypipe
# 输出:Hello from pipe

注意:echo命令会阻塞,直到有另一个进程读取管道中的数据。

类比理解:命名管道就像传声筒或气动管道输送系统。你在一边说话(写入),另一边就能听到(读取)。声音(数据)直接通过管道传递,不需要经过第三者。传声筒有一个名字(文件路径),所以任何知道这个名字的人都可以来使用它。

7. 套接字(Socket)s

套接字是用于进程间通信(IPC)或网络通信的端点。它们可以是Unix域套接字(同一台机器上的进程通信)或网络套接字(不同机器间的通信)。

套接字通常由程序自动创建,你一般不会手动创建它们。你可以在/run//tmp/下看到很多套接字文件。

ls -l /run/dbus/system_bus_socket

输出示例:

srwxrwxrwx 1 root root 0 7月  27 10:15 /run/dbus/system_bus_socket

最左边的s表示套接字。

类比理解:套接字就像电话插座或网线接口。当你的电脑要联网时,你把网线插到网口(套接字)上,数据就可以通过这个接口进出。程序之间通信就像打电话——需要先"拨号"(连接套接字),然后才能"通话"(传输数据)。

3.8.2 ls -l 输出的完整解析

现在你已经知道了文件类型,让我们完整解析ls -l输出的每一列。

ls -l输出示例

ls -l /etc/hosts /bin/ls /dev/sda /dev/null /tmp /home/username

输出示例:

-rwxr-xr-x 1 root   root   137688 1月  10 08:30 /bin/ls
-rw-r--r--  1 root   root      220 1月  10 08:30 /etc/hosts
drwxr-xr-x  5 root   root     4096 7月  27 10:00 /home/username
drwxrwxrwt 15 root   root     4096 7月  27 14:30 /tmp
brw-rw----  1 root   disk        8, 0 7月  27 10:15 /dev/sda
crw-rw-rw-  1 root   root        1, 3 7月  27 10:15 /dev/null

让我们以/bin/ls这一行为例,逐列解析:

-rwxr-xr-x 1 root root 137688 1月  10 08:30 /bin/ls
│└┬┘└┬┘└┬┘││    │    │      │           │
│ │   │   │ │    │    │      │           └─ 文件名
│ │   │   │ │    │    │      └─ 最后修改时间
│ │   │   │ │    │    └─ 文件大小(字节)
│ │   │   │ │    └─ 所属组
│ │   │   │ └─ 所有者
│ │   │   └─ 硬链接数
│ │   └─ 其他用户的权限
│ └─ 所属组的权限
└─ 文件类型和所有者权限
第一列:文件类型和权限(共10个字符)

格式为:[文件类型][所有者权限][组权限][其他用户权限]

文件类型(第1个字符):前面已讲过,-普通、d目录、l链接、b块设备、c字符设备、p管道、s套接字。

权限部分(后9个字符,每3个一组):

位置 代表 可能的值
第2-4个字符 所有者(Owner)的权限 rwx
第5-7个字符 所属组(Group)的权限 rwx
第8-10个字符 其他用户(Others)的权限 rwx

每个权限位的含义:

字符 对普通文件 对目录
r(Read,读) 可以读取文件内容 可以列出目录内容(ls)
w(Write,写) 可以修改文件内容 可以在目录中创建/删除/重命名文件
x(eXecute,执行) 可以执行文件(如果是程序或脚本) 可以进入目录(cd)
- 没有该权限 没有该权限

举例解析

  • -rwxr-xr-x:普通文件,所有者可读可写可执行,组用户可读可执行,其他用户可读可执行。这是典型的可执行程序权限。
  • -rw-r--r--:普通文件,所有者可读可写,组用户只读,其他用户只读。这是典型的普通数据文件权限。
  • drwxr-xr-x:目录,所有者可读可写可进入,组用户可读可进入,其他用户可读可进入。这是典型的公开目录权限。
  • drwx------:目录,只有所有者可以读、写、进入。其他人没有任何权限。这是典型的私人目录权限(如家目录)。
  • lrwxrwxrwx:符号链接。链接文件的权限通常显示为全权限,但实际的访问权限由目标文件决定。
第二列:硬链接数

表示该文件有多少个硬链接(对于目录,表示有多少个子目录+...)。

对于普通文件,如果数字是1,表示只有一个名字指向这个文件。如果是2或更多,表示有多个硬链接(见3.9节)。

对于目录,最小值是2(...)。每增加一个子目录,数字增加1(因为每个子目录里都有一个..指回父目录)。

第三列:所有者(Owner)

显示这个文件属于哪个用户。文件的所有者通常是创建该文件的用户,但可以被root修改。

第四列:所属组(Group)

显示这个文件属于哪个用户组。组权限允许同组的用户以特定方式访问文件。

第五列:文件大小

对于普通文件,显示文件内容的字节数。对于目录,显示目录文件本身的大小(不是目录内容的总大小!)。对于块设备和字符设备,显示主次设备号(如8, 0)。

查看人类可读的大小

ls -lh /etc/hosts /bin/ls

输出示例:

-rwxr-xr-x 1 root root 135K 1月  10 08:30 /bin/ls
-rw-r--r--  1 root root  220 1月  10 08:30 /etc/hosts

135K表示135KB,比看137688字节直观多了。

第六、七、八列:最后修改时间

显示文件最后被修改的日期和时间。如果文件是最近修改的,可能会显示具体的时间(如15:30);如果是很久以前修改的,则显示年份(如2023年)。

第九列:文件名

文件的名称。如果是符号链接,还会显示-> 目标路径

3.8.3 file 命令:识别文件的真实身份

由于Linux不依赖文件扩展名来判断文件类型,file命令就成了你的"文件鉴定师"。它可以检查文件的内容,告诉你这到底是什么类型的文件。

file /bin/ls
file /etc/hosts
file /dev/sda
file /dev/null
file /home/username

输出示例:

/bin/ls:        ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=xxx, stripped
/etc/hosts:     ASCII text
/dev/sda:       block special (8/0)
/dev/null:      character special (1/3)
/home/username: directory

file命令的强大之处

# 识别图片文件
file photo.jpg
# 输出:photo.jpg: JPEG image data, JFIF standard 1.01

# 识别压缩包
file archive.tar.gz
# 输出:archive.tar.gz: gzip compressed data, from Unix

# 识别脚本类型
file myscript
# 输出:myscript: Bourne-Again shell script, ASCII text executable

# 查看多个文件
file *

类比理解file命令就像博物馆里的文物鉴定专家。你拿一个东西给他看,他不需要看标签(扩展名),而是通过观察材质、工艺、风格(文件内容的"魔数"和结构),就能准确判断这是唐代的瓷器、宋代的书画,还是现代的仿品。有些文件故意把标签贴错了(改了扩展名),但专家一看内容就知道真假。

3.8.4 修改文件权限:chmod 命令初步

虽然权限的详细内容我们会在后续章节深入讲解,但在这里先介绍chmod命令的基本用法,让你可以亲手改变文件的"身份档案"。

符号模式(Symbolic Mode)

# 给文件添加可执行权限
chmod +x myscript.sh

# 给文件所有者添加写权限
chmod u+w myfile.txt

# 去掉其他用户的读权限
chmod o-r myfile.txt

# 设置组用户的读写权限
chmod g=rw myfile.txt

# 组合使用
chmod u+rwx,g+rx,o-rwx myfile.txt

其中:

  • u = user(所有者)
  • g = group(组)
  • o = others(其他用户)
  • a = all(所有人,等同于ugo
  • + = 添加权限
  • - = 去掉权限
  • = = 设置权限(覆盖原有)

数字模式(Numeric Mode)

每个权限位用一个数字表示:

  • r = 4
  • w = 2
  • x = 1

三个数字组合分别代表所有者、组、其他用户的权限:

# rwxr-xr-x = 7 5 5
chmod 755 myscript.sh

# rw-r--r-- = 6 4 4
chmod 644 myfile.txt

# rwx------ = 7 0 0
chmod 700 my_private_key

# rwxrwxrwx = 7 7 7
chmod 777 public_directory

类比理解chmod就像调整房间的访问权限。你可以决定:

  • 谁可以进来(x = 进入/执行)
  • 谁可以看里面的东西(r = 读取)
  • 谁可以修改房间里的布置(w = 写入)

chmod 755就像"房主有全套钥匙(读、写、进),访客可以参观但不能改动(读、进),陌生人只能在外面看看(读)“。chmod 700就像"只有房主能进,其他人连门都摸不到”。


3.9 inode与硬链接、软链接

这一节我们要探讨Linux文件系统中一个非常核心、但又非常抽象的概念——inode。理解inode,你就真正理解了Linux文件系统的底层工作原理。同时,我们还会详细讲解硬链接和软链接这两种特殊的文件关联方式。

3.9.1 inode:文件的"灵魂档案"

什么是inode?

**inode(Index Node,索引节点)**是Linux文件系统中用于存储文件元数据(Metadata)的数据结构。每个文件(包括目录、设备文件等)都有一个对应的inode,每个inode都有一个唯一的编号(inode number)。

当你创建一个文件时,文件系统会:

  1. 分配一个空闲的inode,并在其中记录文件的元数据。
  2. 分配一个或多个数据块(Block)来存储文件的实际内容。
  3. 在目录中创建一个目录项(Directory Entry),把文件名和inode编号关联起来。

类比理解:inode就像图书馆的索引卡片每个人的户籍档案。想象一下:

  • 你有一本书(文件内容),存放在图书馆的某个书架的某个位置(数据块)。
  • 图书馆的索引卡片(inode)上记录了:书名、作者、出版日期、页数、ISBN号、存放位置(书架编号和层数)等。
  • 但索引卡片上没有书名本身——书名是写在图书目录(目录项)里的,目录告诉你"《三国演义》对应索引卡片第1234号"。

在Linux中:

  • 文件名不是存储在inode中的!文件名存储在目录文件中。
  • inode中存储的是文件的所有其他信息:大小、权限、所有者、时间戳、数据块位置等。
  • 目录项建立了"文件名 ↔ inode编号"的映射关系。
inode中存储的信息

一个典型的inode包含以下信息:

信息项 说明
inode编号 文件系统内唯一的标识符
文件类型 普通文件、目录、链接、设备等
权限(Mode) 读、写、执行权限
所有者UID 文件所属用户的ID
所属组GID 文件所属组的ID
文件大小 文件内容的字节数
时间戳 访问时间(atime)、修改时间(mtime)、状态改变时间(ctime)
链接数 指向该inode的硬链接数量
数据块指针 指向存储文件内容的数据块的地址

注意:inode中不包含文件名和文件内容!文件名在目录项中,文件内容在数据块中。

查看文件的inode编号
ls -i /etc/hosts

输出示例:

131073 /etc/hosts

131073就是/etc/hosts的inode编号。

# 查看多个文件的inode
ls -i /etc/passwd /bin/ls /tmp

输出示例:

131074 /etc/passwd
  1234 /bin/ls
    67 /tmp
查看inode的详细信息:stat命令
stat /etc/hosts

输出示例:

  文件:/etc/hosts
  大小:220             块:8          IO 块:4096   普通文件
设备:fd00h/64768d      Inode:131073      硬链接:1
权限:(0644/-rw-r--r--)  Uid:(    0/    root)   Gid:(    0/    root)
最近访问:2024-07-27 10:15:32.000000000 +0800
最近更改:2024-01-10 08:30:00.000000000 +0800
最近改动:2024-01-10 08:30:00.000000000 +0800
创建时间:-

stat输出的关键字段解析

字段 说明
大小 文件内容的字节数
占用的磁盘块数
IO 块 文件系统的块大小
设备 文件所在的设备标识
Inode inode编号
硬链接 指向该inode的硬链接数量
权限 文件的权限位
Uid/Gid 所有者和组的ID及名称
最近访问(atime) 最后一次读取文件内容的时间
最近更改(mtime) 最后一次修改文件内容的时间
最近改动(ctime) 最后一次修改inode元数据的时间(包括权限、所有者等)

重要区别

  • mtime(修改时间):文件内容被修改的时间。比如你编辑了一个文本文件并保存,mtime会更新。
  • ctime(改动时间):inode信息被修改的时间。比如你改变了文件的权限(chmod)、所有者(chown),或者修改了文件内容(修改内容会导致数据块变化,进而更新inode中的块指针,所以ctime也会变),ctime都会更新。
  • atime(访问时间):文件内容被读取的时间。比如你cat了一个文件,atime理论上会更新。但为了减少磁盘I/O,现代Linux通常使用"相对更新"策略(relatime),不会每次读取都更新atime。

类比理解:inode就像每个人的身份证+档案袋。身份证上有你的身份证号(inode编号)、性别(文件类型)、出生日期(时间戳)、家庭住址(数据块指针)等。但身份证上没有你的"名字"——你的名字登记在户口本(目录)上,户口本里写着"姓名:张三,身份证号:123456789"。如果你改了名字(重命名文件),只需要换一本户口本(修改目录项),不需要重新办身份证(inode不变)。但如果你整容了(修改文件内容),档案袋里关于你外貌的描述就要更新(mtime变),同时档案袋的封口记录也要更新(ctime变)。

inode的数量限制

在传统文件系统(如ext2/ext3/ext4)中,inode的数量是在创建文件系统时就确定好的。这意味着:

  • 即使你的硬盘还有很多空闲空间,如果inode用完了,你也无法再创建新文件!
  • 这种情况通常发生在存储了大量小文件的场景(比如邮件服务器、缓存服务器)。

查看文件系统的inode使用情况

df -i

输出示例:

文件系统         Inode 已用(I) 可用(I) 已用(I)% 挂载点
/dev/sda1      655360   15234  640126      3% /
/dev/sdb1      262144     123  262021      1% /data

在现代文件系统(如XFS、Btrfs)中,inode通常是动态分配的,不存在这个问题。

3.9.2 硬链接(Hard Link)

什么是硬链接?

**硬链接(Hard Link)**是文件系统中的一个额外目录项,它指向一个已存在的inode。换句话说,硬链接给同一个inode起了另外一个名字。

当你创建一个硬链接时:

  • 没有创建新的inode。
  • 没有复制文件内容。
  • 只是在某个目录中新增了一个"文件名 → inode编号"的映射。
  • inode中的"链接数"会增加1。

创建硬链接

# 先创建一个原始文件
echo "Original content" > original.txt

# 创建硬链接
ln original.txt hardlink.txt

# 查看
ls -li original.txt hardlink.txt

输出示例:

131075 -rw-r--r-- 2 username username 17 7月  27 16:00 hardlink.txt
131075 -rw-r--r-- 2 username username 17 7月  27 16:00 original.txt

注意:

  • 两行的inode编号都是131075,说明它们指向同一个inode。
  • 硬链接数都是2(第三列的数字)。
  • 文件大小、权限、时间戳完全相同。

硬链接的特性

  1. 共享inode和数据:硬链接和原文件完全等价,它们共享同一个inode和同一组数据块。
  2. 不能跨文件系统:硬链接只能在同一个文件系统内创建,因为不同文件系统的inode编号空间是独立的。
  3. 不能链接目录:为了防止形成目录循环(A链接到B,B又链接回A),普通用户不能对目录创建硬链接(root在某些条件下可以,但需要特殊处理)。
  4. 删除原文件不影响硬链接:删除原文件只是删除了一个目录项,inode的链接数减1。只要链接数不为0,文件内容就仍然存在,可以通过硬链接访问。

删除原文件后的情况

# 删除原文件
rm original.txt

# 硬链接仍然可以访问
cat hardlink.txt
# 输出:Original content

# 查看硬链接的inode
ls -li hardlink.txt

输出示例:

131075 -rw-r--r-- 1 username username 17 7月  27 16:00 hardlink.txt

注意:链接数变成了1,但inode编号还是131075,文件内容完好无损。

类比理解:硬链接就像同一套房子的多把钥匙。假设你买了一套房子(文件内容),办了一个房产证(inode)。现在你配了一把新钥匙(创建硬链接),新钥匙和老钥匙都能打开同一扇门(访问同一个inode)。房子只有一套(数据只有一份),但开门的钥匙可以有多把(多个文件名)。

即使你把老钥匙丢了(删除原文件),新钥匙仍然能开门(硬链接仍然可以访问数据)。只有当所有钥匙都丢了(所有硬链接都被删除,链接数变为0),房子才真正"没人要了"(文件系统回收inode和数据块)。

硬链接的用途

  1. 重要文件的备份保护:为重要文件创建硬链接到另一个目录,即使原文件被误删,硬链接仍然保留数据。
  2. 节省空间:不需要复制文件内容,就能在多个位置"出现"。
  3. 文件版本管理:某些备份工具使用硬链接来实现增量备份,未改变的文件通过硬链接共享,只备份改变的文件。

3.9.3 软链接/符号链接(Symbolic Link / Soft Link)

什么是软链接?

软链接(Soft Link),也叫符号链接(Symbolic Link),是一个特殊的文件,它存储的是目标文件的路径名。软链接有自己的inode,有自己的数据块,但数据块里存放的不是文件内容,而是指向目标的路径字符串。

当你访问一个软链接时,操作系统会:

  1. 读取软链接的数据块,获取其中存储的路径。
  2. 根据这个路径找到真正的目标文件。
  3. 对目标文件进行实际操作。

创建软链接

# 创建一个原始文件
echo "Target content" > target.txt

# 创建软链接
ln -s target.txt symlink.txt

# 查看
ls -li target.txt symlink.txt

输出示例:

131076 -rw-r--r-- 1 username username 15 7月  27 16:10 target.txt
131077 lrwxrwxrwx 1 username username 10 7月  27 16:10 symlink.txt -> target.txt

注意:

  • target.txt的inode是131076
  • symlink.txt的inode是131077,这是一个完全不同的inode!
  • symlink.txt的文件大小是10字节,这正好是字符串"target.txt\0"的长度(它存储的就是目标路径)。
  • 权限显示为rwxrwxrwx,但实际的访问权限由目标文件决定。

软链接的特性

  1. 有自己的inode:软链接是一个独立的文件,有自己的inode和数据块。
  2. 可以跨文件系统:因为软链接存储的是路径字符串,不是inode编号,所以可以指向任何位置的文件,包括其他文件系统、甚至不存在的文件。
  3. 可以链接目录:软链接可以指向目录,这是非常常见的用法。
  4. 目标删除后成为"悬空链接":如果目标文件被删除或移动,软链接就指向了一个不存在的路径,成为"悬空链接"(Dangling Link),访问时会报错。

目标删除后的情况

# 删除目标文件
rm target.txt

# 尝试访问软链接
cat symlink.txt

输出示例:

cat: symlink.txt: 没有那个文件或目录
# 查看软链接状态
ls -l symlink.txt

输出示例:

lrwxrwxrwx 1 username username 10 7月  27 16:10 symlink.txt -> target.txt

注意:软链接还在,但它指向的目标已经不存在了。红色显示(在支持颜色的终端中)通常表示这是一个损坏的链接。

修复悬空链接

# 重新创建目标文件
echo "New content" > target.txt

# 现在软链接又正常工作了
cat symlink.txt
# 输出:New content

类比理解:软链接就像路标、指示牌或快递单上的地址。假设你在小区里看到一块指示牌:“向前50米右转→社区服务中心”。这块指示牌本身(软链接)不是服务中心,它只是告诉你服务中心在哪里。指示牌是独立存在的(有自己的inode),你可以把它放在任何地方(可以跨文件系统)。

如果服务中心搬迁了(目标文件被移动或删除),指示牌还在原地,但它指向了一个空房子。你看到指示牌走过去,发现"没有那个地方"(报错)。如果服务中心在原址重新开张(重新创建同名文件),指示牌又有效了。

软链接指向目录的常见用法

# 为长路径创建快捷访问方式
ln -s /var/log/nginx /home/username/nginx-logs

# 现在可以通过短路径访问
cd ~/nginx-logs
ls

# 软件版本管理
ln -s /opt/python-3.11 /usr/local/bin/python3

# 配置文件的标准位置链接到实际位置
ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled/default

3.9.4 硬链接 vs 软链接:全面对比

对比项 硬链接(Hard Link) 软链接/符号链接(Symbolic Link)
inode 与原文件共享同一个inode 有自己的独立inode
数据块 与原文件共享同一组数据块 数据块中存储目标路径字符串
文件内容 和原文件完全相同(实际是同一组数据) 本身没有实际内容,只是指向目标
跨文件系统 不可以(inode编号只在同一文件系统内有效) 可以(存储的是路径字符串)
链接目录 不可以(普通用户) 可以
链接不存在的目标 不可以 可以(创建悬空链接)
目标删除后 仍然可以正常访问(链接数减1) 成为悬空链接,无法访问
文件大小 和原文件相同 等于目标路径字符串的长度
权限显示 和原文件相同 通常为rwxrwxrwx(实际权限取决于目标)
ls -l标识 无特殊标识,链接数>1 l标识,显示-> 目标路径
创建命令 ln 源文件 硬链接名 ln -s 目标路径 软链接名
用途 备份保护、节省空间、多位置访问同一数据 快捷方式、版本切换、配置文件管理、简化长路径

类比总结

  • 硬链接 = 同一套房子的多把钥匙:房子只有一套,钥匙可以有多把。任何一把钥匙都能开门。丢掉一把钥匙不影响其他钥匙。
  • 软链接 = 路标/指示牌:路标独立存在,告诉你目标在哪里。目标搬家了,路标就失效了。路标可以指向任何地方,包括其他城市的建筑(跨文件系统)。

3.9.5 查找和清理链接

查找所有的硬链接(指向同一个inode的所有文件名):

# 先找到文件的inode编号
ls -i /etc/hosts
# 假设输出:131073 /etc/hosts

# 然后在整个文件系统中查找指向这个inode的文件
find / -inum 131073 2>/dev/null

注意:因为不能跨文件系统,所以find必须在同一个文件系统内搜索。

查找所有的软链接

# 查找当前目录下的所有软链接
find . -type l

# 查找并显示它们指向的目标
find . -type l -ls

# 查找悬空的软链接
find . -type l ! -readable

# 或者更精确地
find . -type l -xtype l

查看软链接指向的最终目标

# readlink 显示软链接指向的路径
readlink symlink.txt

# readlink -f 显示最终解析的绝对路径(跟随所有链接)
readlink -f symlink.txt

3.10 文件系统挂载与卸载

3.10.1 什么是挂载

在3.2节中我们讲过,Linux只有一个统一的目录树,所有的存储设备(硬盘分区、U盘、光盘、网络共享等)都需要"接入"到这个目录树的某个位置才能被访问。这个"接入"的过程就叫做挂载(Mount)

挂载的本质:将一个文件系统(存储在某个设备上的数据组织结构)关联到目录树中的一个目录(称为"挂载点")上。挂载后,访问这个挂载点目录,就是在访问该文件系统的内容。

类比理解:挂载就像给手机安装SIM卡把游戏卡带插入游戏机。手机本身有操作系统(Linux目录树),但如果没有SIM卡(存储设备),你就不能打电话(访问数据)。你把SIM卡插入卡槽(挂载到某个挂载点),手机就识别了这张卡,你可以使用里面的联系人和短信了。当你要换卡时,先弹出旧卡(卸载),再插入新卡(挂载)。

另一个类比:挂载就像商场里的品牌入驻。整个商场是一个统一的空间(Linux目录树),但每个品牌(文件系统)有自己的货品(数据)。品牌入驻时,会租用商场里的某个铺位(挂载点)。顾客走进这个铺位,就能看到该品牌的货品。品牌撤柜时(卸载),铺位就空了。

3.10.2 mount 命令:挂载文件系统

基本语法
mount [选项] 设备 挂载点

或者:

mount [选项] -t 文件系统类型 设备 挂载点

最简单的挂载示例

# 1. 创建挂载点目录(如果还没有)
sudo mkdir -p /mnt/mydisk

# 2. 挂载设备(假设设备是 /dev/sdb1)
sudo mount /dev/sdb1 /mnt/mydisk

# 3. 现在可以访问挂载点下的内容了
ls /mnt/mydisk
查看当前已挂载的文件系统
# 方法1:直接运行 mount
mount

# 方法2:查看 /proc/mounts
cat /proc/mounts

# 方法3:查看 /etc/mtab
cat /etc/mtab

# 方法4:使用 df -h
df -h

mount命令的输出示例(部分):

/dev/sda2 on / type ext4 (rw,relatime)
/dev/sda1 on /boot type ext4 (rw,relatime)
/dev/sdb1 on /mnt/mydisk type ext4 (rw,relatime)
tmpfs on /run type tmpfs (rw,nosuid,nodev,seclabel,mode=755)

每一行的格式:设备 on 挂载点 type 文件系统类型 (挂载选项)

指定文件系统类型

如果mount无法自动识别文件系统类型,你需要用-t指定:

# 挂载一个ext4分区
sudo mount -t ext4 /dev/sdb1 /mnt/mydisk

# 挂载一个Windows的NTFS分区(需要安装ntfs-3g)
sudo mount -t ntfs-3g /dev/sdc1 /mnt/windows

# 挂载一个ISO镜像文件(使用loop设备)
sudo mount -t iso9660 -o loop /path/to/image.iso /mnt/iso

# 挂载一个NFS网络共享
sudo mount -t nfs 192.168.1.100:/shared /mnt/nfs

# 挂载一个CIFS/SMB共享(Windows共享)
sudo mount -t cifs //192.168.1.100/share /mnt/smb -o username=guest
常用的挂载选项(-o)
选项 说明
ro 只读挂载(Read-Only)
rw 读写挂载(Read-Write,默认)
noexec 禁止执行挂载点中的程序
nosuid 忽略SUID和SGID权限位
nodev 不解释设备文件
sync 同步写入(安全但慢)
async 异步写入(默认,快但断电可能丢数据)
auto / noauto 是否被mount -a自动挂载
user / nouser 是否允许普通用户挂载/卸载
defaults 默认选项(等于rw,suid,dev,exec,auto,nouser,async

示例

# 只读挂载(保护数据不被意外修改)
sudo mount -o ro /dev/sdb1 /mnt/mydisk

# 禁止执行和SUID(安全挂载未知来源的设备)
sudo mount -o noexec,nosuid,nodev /dev/sdb1 /mnt/mydisk

# 以特定用户和组身份挂载(如挂载Windows分区时指定文件所有者)
sudo mount -o uid=1000,gid=1000,umask=022 /dev/sdc1 /mnt/windows
挂载ISO镜像文件
# 创建挂载点
sudo mkdir -p /mnt/iso

# 挂载ISO文件(loop设备允许把文件当作块设备使用)
sudo mount -o loop ubuntu-22.04.iso /mnt/iso

# 查看ISO内容
ls /mnt/iso

# 卸载
sudo umount /mnt/iso
挂载U盘或移动硬盘
# 1. 插入U盘后,查看系统识别到的设备
dmesg | tail -20
# 或者
lsblk

# 2. 假设U盘被识别为 /dev/sdc1
# 创建挂载点
sudo mkdir -p /mnt/usb

# 3. 挂载(VFAT/exFAT格式通常用于U盘)
sudo mount -t vfat /dev/sdc1 /mnt/usb
# 或者如果是exFAT
sudo mount -t exfat /dev/sdc1 /mnt/usb

# 4. 使用
ls /mnt/usb

# 5. 卸载(必须先卸载才能安全拔出!)
sudo umount /mnt/usb

3.10.3 umount 命令:卸载文件系统

基本语法
umount 挂载点
# 或者
umount 设备

卸载示例

# 通过挂载点卸载
sudo umount /mnt/mydisk

# 或者通过设备名卸载
sudo umount /dev/sdb1
卸载失败的常见原因
  1. 设备忙(Device is busy):有进程正在使用挂载点中的文件或目录。

    # 报错:umount: /mnt/mydisk: target is busy
    
    # 查找哪些进程在使用这个挂载点
    sudo lsof /mnt/mydisk
    # 或者
    sudo fuser -m /mnt/mydisk
    
    # 终止这些进程(谨慎使用!)
    sudo fuser -km /mnt/mydisk
    
    # 然后再卸载
    sudo umount /mnt/mydisk
    
  2. 当前目录在挂载点内:你自己的shell当前就在挂载点目录下。

    # 错误:你在 /mnt/mydisk 目录下执行 umount /mnt/mydisk
    
    # 解决:先离开挂载点
    

cd /
sudo umount /mnt/mydisk


3. **有用户通过该挂载点登录**:如果用户的家目录在这个挂载点上,或者有进程通过chroot进入该挂载点。

**安全卸载的重要性**:

在拔出U盘或移动硬盘之前,**必须先执行umount**!否则:
- 缓存的数据可能还没有写入设备,导致数据丢失或损坏。
- 文件系统可能处于不一致的状态。

**类比理解**:卸载就像**你整理行李箱准备离开酒店**。你不能直接拖着没拉好拉链的箱子就走(直接拔U盘),否则里面的东西会掉出来(数据丢失)。你需要先整理好、拉上拉链(umount确保所有数据都写入磁盘),然后才能安全离开。

### 3.10.4 /etc/fstab:开机自动挂载的"日程表"

每次开机都要手动mount所有分区显然不现实。`/etc/fstab`(File System Table)文件就是用来定义**开机时自动挂载哪些文件系统**的配置文件。

#### fstab文件的格式

fstab文件的每一行包含6个字段:

<文件系统> <挂载点> <类型> <选项>


| 字段 | 说明 | 示例 |
|-----|------|------|
| 1. 文件系统 | 要挂载的设备或远程共享 | `/dev/sda1`、`UUID=xxx`、`LABEL=MyData`、`192.168.1.100:/nfs` |
| 2. 挂载点 | 目录树中的挂载位置 | `/`、`/home`、`/mnt/data` |
| 3. 类型 | 文件系统类型 | `ext4`、`xfs`、`vfat`、`ntfs-3g`、`nfs`、`swap` |
| 4. 选项 | 挂载选项 | `defaults`、`rw,noatime`、`noauto` |
| 5. dump | 是否被dump命令备份(0=不备份,1=备份) | `0`或`1` |
| 6. pass | fsck检查顺序(0=不检查,1=根目录优先,2=其他) | `0`、`1`、`2` |

#### 一个典型的/etc/fstab示例

```bash
cat /etc/fstab

输出示例:

#
# /etc/fstab
# Created by anaconda on Mon Jan 10 08:30:00 2024
#
# Accessible filesystems, by reference, are maintained under '/dev/disk/'.
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info.
#
UUID=aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee   /           ext4    defaults        1 1
UUID=ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj   /boot       ext4    defaults        1 2
UUID=kkkk-llll                              /boot/efi   vfat    umask=0077,shortname=winnt 0 2
UUID=mmmmmmmm-nnnn-oooo-pppp-qqqqqqqqqqqq   /home       ext4    defaults        1 2
/dev/mapper/centos-swap                     none        swap    defaults        0 0
/dev/cdrom                                  /mnt/cdrom  iso9660 defaults,noauto,ro 0 0
UUID=rrrrrrrr-ssss-tttt-uuuu-vvvvvvvvvvvv   /mnt/data   ext4    defaults,noauto   0 0
使用UUID而不是设备名

为什么要用UUID=xxx而不是/dev/sda1?因为:

  • 设备名(如/dev/sda1)可能会变化。比如你插了一个新的硬盘,原来的sdb可能变成了sdc
  • UUID(Universally Unique Identifier)是文件系统在创建时分配的,终身不变,更加可靠。

查看分区的UUID

# 方法1:blkid
sudo blkid

# 方法2:lsblk
lsblk -f

# 方法3:查看 /dev/disk/by-uuid/
ls -l /dev/disk/by-uuid/

输出示例(blkid)

/dev/sda1: UUID="aaaa-bbbb" BLOCK_SIZE="512" TYPE="vfat" PARTLABEL="EFI System Partition" PARTUUID="xxxx-xxxx"
/dev/sda2: UUID="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="yyyy-yyyy"
/dev/sda3: UUID="ffffffff-gggg-hhhh-iiii-jjjjjjjjjjjj" BLOCK_SIZE="4096" TYPE="ext4" PARTUUID="zzzz-zzzz"
添加自定义挂载到fstab

假设你想让系统在开机时自动挂载一个数据分区:

# 1. 找到分区的UUID
sudo blkid /dev/sdb1
# 假设输出:/dev/sdb1: UUID="1234abcd-56ef-78gh-90ij-klmnopqrstuv" TYPE="ext4"

# 2. 创建挂载点
sudo mkdir -p /mnt/data

# 3. 先手动测试挂载是否成功
sudo mount UUID="1234abcd-56ef-78gh-90ij-klmnopqrstuv" /mnt/data
ls /mnt/data
sudo umount /mnt/data

# 4. 添加到 /etc/fstab(先备份!)
sudo cp /etc/fstab /etc/fstab.backup

# 5. 编辑 fstab,添加一行
echo 'UUID=1234abcd-56ef-78gh-90ij-klmnopqrstuv   /mnt/data   ext4   defaults   0   2' | sudo tee -a /etc/fstab

# 6. 验证fstab语法是否正确(非常重要!)
sudo mount -a

# 如果没有报错,说明fstab格式正确,所有定义的文件系统都已成功挂载
# 如果有报错,立即用备份恢复!
# sudo cp /etc/fstab.backup /etc/fstab

警告:修改/etc/fstab时一定要小心!如果fstab中有错误,系统可能无法正常启动。修改前务必备份,修改后用mount -a验证。

noauto选项:不自动挂载

如果你不想某个文件系统在开机时自动挂载,但希望以后能方便地手动挂载,可以使用noauto选项:

UUID=xxx   /mnt/backup   ext4   defaults,noauto   0   0

这样开机时不会自动挂载,但以后可以简单地用sudo mount /mnt/backup挂载(因为fstab中已经定义了设备和类型)。

3.10.5 df 命令:查看磁盘空间使用情况

df(disk free)命令用于显示文件系统的磁盘空间使用情况。

# 基本用法
df

# 人类可读格式(推荐)
df -h

# 显示文件系统类型
df -T

# 显示某个目录所在文件系统的空间
df -h /home

# 显示inode使用情况
df -i

df -h输出示例

文件系统        容量  已用  可用 已用% 挂载点
devtmpfs        3.9G     0  3.9G    0% /dev
tmpfs           3.9G     0  3.9G    0% /dev/shm
tmpfs           3.9G  8.6M  3.9G    1% /run
tmpfs           3.9G     0  3.9G    0% /sys/fs/cgroup
/dev/sda2        50G   15G   36G   30% /
/dev/sda1      1014M  215M  800M   22% /boot
/dev/sda3       200G   50G  150G   25% /home
tmpfs           782M     0  782M    0% /run/user/1000

列说明

说明
文件系统 设备或虚拟文件系统名
容量 总容量
已用 已使用的空间
可用 剩余可用空间
已用% 使用百分比
挂载点 挂载位置

类比理解df就像查看每个储物柜的使用情况。你有一排储物柜(文件系统),每个柜子有总容量(容量)、已经放了多少东西(已用)、还剩多少空间(可用)。这帮你决定应该把新物品放在哪个柜子里。

3.10.6 du 命令:查看目录/文件的磁盘占用

du(disk usage)命令用于估算文件和目录的磁盘使用空间。与df看"整个文件系统"不同,du看"具体的目录或文件"。

# 查看当前目录的总大小
du -sh

# 查看某个目录的大小
du -sh /var/log

# 查看当前目录下所有子目录的大小
du -h --max-depth=1

# 查看当前目录下所有文件和目录的大小,并排序
du -sh * | sort -h

# 查看某个文件的大小
du -h /etc/hosts

# 查看系统中最大的10个目录
sudo du -h / 2>/dev/null | sort -rh | head -10

du -sh /var/log输出示例

856M    /var/log

du -h --max-depth=1 /var/log输出示例

0       /var/log/btmp
8.0K    /var/log/grubby
4.0K    /var/log/tallylog
4.0K    /var/log/wtmp
12K     /var/log/anaconda
24K     /var/log/tuned
56K     /var/log/cups
88K     /var/log/audit
100K    /var/log/libvirt
120K    /var/log/samba
252K    /var/log/cron
348K    /var/log/messages
840M    /var/log/journal
856M    /var/log

du的常用选项

选项 说明
-s 只显示总计,不显示子目录
-h 人类可读格式
-a 显示所有文件和目录
--max-depth=N 只显示N层深度的子目录
-c 最后显示总计
-L 跟随符号链接
--exclude=模式 排除匹配的文件

df 和 du 的区别

命令 查看范围 用途
df 整个文件系统 查看分区级别的空间使用情况
du 特定目录或文件 查看具体文件夹占用了多少空间

类比理解

  • df就像看每个仓库的总容量和剩余空间。仓库管理员需要知道这个仓库还能不能进货。
  • du就像盘点某个货架上的货物占了多少地方。你想知道"小说区的书架一共占了多少平米",或者"这本大百科全书有多厚"。

注意:有时候dfdu看到的结果不一致。比如一个文件被删除了但还有进程打开它,df会显示空间已释放(因为文件系统层面标记为可用),但du可能还显示旧大小(因为它遍历目录)。或者反过来,如果文件被删除但进程还占用,df显示空间没释放,而du不显示该文件(因为目录项已删除)。


本章小结

亲爱的读者,如果你已经读到了这里,恭喜你!你已经完成了Linux文件系统与目录结构这一核心章节的学习。这一章的内容非常密集,涵盖了Linux系统最基础也最重要的知识体系。让我们用一张"知识地图"来回顾一下本章的精华内容。

核心概念回顾

1. 文件系统(3.1节)

  • 文件系统是组织、存储、检索和管理数据的软件机制,就像图书馆的索引系统。
  • Linux支持多种文件系统:ext4(最常用、最稳定)、XFS(大容量、高并发)、Btrfs(新一代、功能丰富)、F2FS(闪存优化)等。
  • 核心功能包括:存储空间管理、文件命名与组织、元数据管理、数据保护、用户接口。

2. Linux目录结构(3.2节)

  • Linux采用单一的树形结构,所有文件和目录都从根目录/开始。
  • 与Windows的多根结构(C盘、D盘)不同,Linux通过"挂载"将不同分区接入统一的目录树。
  • FHS(文件系统层次结构标准)定义了各标准目录的用途,保证了不同发行版的一致性。

3. 核心目录解析(3.3节)

  • /bin/sbin:系统启动必需的基本命令(求生包和维修工具箱)。
  • /lib/lib64:共享库文件(公共工具房)。
  • /boot:启动文件(发动机舱)。
  • /dev:设备文件(化妆间/设备化身)。
  • /proc/sys:虚拟文件系统,暴露内核和系统信息(监护仪屏幕和户籍档案室)。
  • /run:运行时数据(临时便签板)。
  • /media/mnt:外部设备挂载点(自动寄存柜和临时会客室)。
  • /opt:第三方软件(外籍人士公寓区)。
  • /srv:服务数据(发货仓库)。

4. bin目录的区别(3.4节)

  • /bin:启动必需的用户命令。
  • /sbin:启动必需的系统管理命令。
  • /usr/bin:普通应用程序。
  • /usr/sbin:非关键的系统管理命令。
  • /usr/local/bin:手动安装的程序。
  • PATH环境变量决定了系统查找命令的顺序。

5. /etc配置文件(3.5节)

  • /etc是系统的"大脑",存放所有配置文件。
  • 关键文件包括:/etc/hostname/etc/hosts/etc/passwd/etc/shadow/etc/fstab/etc/ssh/sshd_config等。
  • 修改前务必备份!

6. /var、/tmp、/home(3.6节)

  • /var:动态变化的数据(日志、缓存、队列、状态)。
  • /tmp:临时文件,全局可写,重启后清空。
  • /home:普通用户的私人领地,每个用户有自己的家目录。

7. 绝对路径与相对路径(3.7节)

  • 绝对路径从/开始,唯一确定一个位置(完整邮政地址)。
  • 相对路径从当前目录出发(本地问路指引)。
  • . = 当前目录,.. = 父目录,~ = 家目录,- = 上次目录。

8. 文件类型与属性(3.8节)

  • Linux有七种文件类型:普通文件、目录、符号链接、块设备、字符设备、命名管道、套接字。
  • ls -l输出包含:类型、权限、链接数、所有者、组、大小、时间、文件名。
  • file命令可以识别文件的真实类型。
  • chmod命令可以修改文件权限。

9. inode与链接(3.9节)

  • inode是文件的"灵魂档案",存储元数据但不存储文件名和内容。
  • 硬链接:同一inode的多个名字(同一套房子的多把钥匙)。
  • 软链接:存储目标路径的特殊文件(路标/指示牌)。
  • 硬链接不能跨文件系统、不能链接目录;软链接可以。

10. 挂载与卸载(3.10节)

  • mount将文件系统接入目录树,umount将其移除。
  • /etc/fstab定义开机自动挂载。
  • df查看文件系统空间,du查看目录/文件占用空间。

给零基础小白的建议

  1. 多动手实践:这一章的概念很多,只看是记不住的。打开你的Linux系统(无论是虚拟机、WSL还是实体机),亲自执行每一个命令,观察输出结果。

  2. 多用ls -lcd:这两个命令是你探索Linux世界的"双腿"。没事就到处逛逛,看看每个目录里有什么,熟悉目录结构。

  3. 不要怕犯错:在/tmp目录里随便创建文件、删除文件、创建链接,做实验。/tmp就是给你折腾的。

  4. 建立"空间感":试着在脑海中构建Linux目录树的地图。当你知道/var/log在哪里、/etc/hosts在哪里时,你就迈出了成为Linux高手的第一步。

  5. 记住核心原则:在Linux中,一切皆文件。设备是文件、进程信息是文件、系统参数也是文件。这种统一的设计哲学是Linux强大和优雅的根本。


实战练习

光说不练假把式。下面为你准备了由浅入深的实战练习,建议你逐一完成,巩固本章所学。

练习一:目录探索之旅(基础)

目标:熟悉Linux根目录下的核心目录。

  1. 使用cd /进入根目录,然后用ls -l查看根目录下的所有内容。数一数有多少个目录?

  2. 依次进入/bin/sbin/usr/bin/usr/sbin目录,分别用ls | wc -l统计每个目录下有多少个命令。哪个目录的命令最多?

  3. 查看/lib64目录下的libc.so.6文件,使用ls -lfile命令分别查看它的信息。

  4. 进入/dev目录,找出其中的块设备(以b开头)和字符设备(以c开头)各至少3个。

  5. 查看/proc/cpuinfo/proc/meminfo,找出你的CPU型号和系统总内存。

  6. 查看/sys/class/net/目录,你有哪些网络接口?

练习二:路径导航大挑战(基础)

目标:熟练掌握绝对路径和相对路径的使用。

  1. 无论你当前在哪个目录,使用绝对路径查看/etc/passwd文件的前5行。

  2. 进入/var/log目录,然后使用相对路径查看/etc/hosts的内容(提示:需要向上走两级再进入etc)。

  3. 在家目录下创建一个名为linux_practice的目录,进入该目录后:

    • 用相对路径在家目录下创建一个空文件~/testfile.txt
    • 用相对路径在/tmp目录下创建一个名为mytemp的文件
    • cd -linux_practice/tmp之间来回切换3次
  4. /usr/share/doc目录出发,使用相对路径进入/var/log目录(用最少的../组合)。

练习三:文件类型与权限识别(进阶)

目标:能准确识别文件类型和权限。

  1. 执行以下命令,记录每一行的第一列字符,并说明对应的文件类型:

    ls -l /etc/hosts /bin/ls /dev/sda /dev/null /tmp /home/$USER /proc/cpuinfo
    
  2. 在家目录下创建一个名为myscript.sh的文件,写入以下内容:

    #!/bin/bash
    echo "Hello, Linux!"
    

    然后给它添加可执行权限,并尝试执行它(使用./myscript.sh)。

  3. 创建一个目录secret_dir,将其权限设置为只有你自己可以读、写、进入(700)。用另一个用户(如果有的话)尝试进入该目录,观察权限拒绝的报错。

  4. 使用file命令识别以下文件的类型(如果系统中有这些文件的话):/bin/ls/etc/hosts/dev/sda/usr/bin/python3

练习四:inode与链接实验(进阶)

目标:深入理解inode、硬链接和软链接。

  1. 在家目录下创建一个文件original.txt,写入任意内容。使用ls -li查看它的inode编号。

  2. original.txt创建一个硬链接hardlink.txt,再用ls -li查看。验证两者的inode编号是否相同,链接数是否为2。

  3. original.txt创建一个软链接symlink.txt,用ls -li查看。验证软链接是否有自己的inode,文件大小是否等于目标路径的长度。

  4. 删除original.txt,然后分别尝试访问hardlink.txtsymlink.txt。观察结果并解释原因。

  5. 使用find命令查找系统中所有的软链接(从/usr目录开始搜索即可,避免搜索整个根目录耗时太长)。

  6. 使用stat命令查看/etc/passwd的详细信息,解释atimemtimectime分别代表什么。

练习五:挂载与磁盘管理(高级)

目标:掌握文件系统的挂载、卸载和空间查看。

  1. 使用df -h查看你系统的磁盘空间使用情况。哪个分区使用率最高?还剩多少空间?

  2. 使用df -T查看各分区的文件系统类型。你的根分区用的是什么文件系统?

  3. 使用du -sh查看以下目录的大小:/var/log/tmp/home/$USER。哪个目录占用空间最大?

  4. 使用du -h --max-depth=1 /var查看/var下各个子目录的大小,找出占用空间最大的3个子目录。

  5. 查看你的/etc/fstab文件,列出其中定义的所有挂载点。哪些是在开机时自动挂载的?哪些使用noauto选项?

  6. (可选,需要U盘或光盘):插入一个U盘,使用dmesg | taillsblk找到它的设备名,然后手动挂载到/mnt/usb目录,查看内容,最后安全卸载。

练习六:综合挑战(融会贯通)

目标:综合运用本章知识解决实际问题。

场景:你是一名刚入职的系统管理员,需要完成以下任务:

  1. 公司服务器上的/var/log目录快满了。请找出/var/log下最大的5个文件或子目录,并给出它们的大小。

  2. 你需要在服务器上安装一个自己编译的Nginx服务器。请说明应该把Nginx的可执行文件放在哪个目录?配置文件放在哪里?网站数据放在哪里?日志放在哪里?并解释原因。

  3. 你发现/tmp目录下有很多以tmp.开头的旧文件,怀疑是某个程序泄漏的临时文件。请写一个命令,找出/tmp下7天没有被访问过的文件。

  4. 你需要为公司的备份脚本创建一个快捷方式,让运维人员可以通过/backup这个简单的路径访问到实际的备份目录/mnt/data/backup_2024。请使用正确的链接方式实现,并解释为什么选择这种链接。

  5. 你的同事不小心删除了一个重要的配置文件/etc/nginx/nginx.conf,但你记得之前为这个文件创建过硬链接/root/nginx.conf.backup。请解释为什么这个硬链接可能救了你,并说明应该如何恢复。


恭喜你完成了第三章的学习!

文件系统与目录结构是Linux的根基。就像学武术要先扎马步一样,掌握了这一章的内容,你在后续学习用户管理、权限控制、Shell脚本、系统服务等内容时,就会觉得如鱼得水。记住:在Linux的世界里,"知道东西在哪里"和"知道如何到达那里"同样重要。继续加油,下一章我们将深入探讨Linux的权限系统,那才是Linux安全之道的精髓所在!

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐