先建立一张「存储全景图」:一块裸盘怎样一步步变成你能 cd 进去的目录。每个概念都按费曼方式讲——先说人话、再打比方(把硬盘当毛坯仓库、把格式化作装货架做台账)、最后用「删掉这层会怎样」反证分层为什么必须存在。理解了「块设备 → 分区 → 文件系统 → 挂载 → 目录树」这条链,再看 lsblk / fdisk / mkfs / mount 才知道每一步在解决什么问题。随后是配额、软 RAID、LVM 三件进阶武器。操作有风险,务必在快照后练。
Linux 里没有 C 盘 D 盘的概念。一块新硬盘插上机器,要经过分区 → 格式化(建文件系统)→ 挂载三步,才能被当成「文件夹」访问。下面这张图是本章的总纲,后面所有命令都只是在这条链的某一环上干活。
你手上是一块光秃秃的空地(新硬盘)。现在要让人能进去买菜(读写文件),你会怎么干?
换成 Linux 的说法,这四步一模一样:
空地 = 块设备(/dev/sdb);砌隔墙贴平面图 = 分区 + 分区表(fdisk);装货架做台账 = 格式化建文件系统(mkfs);挂门牌接进导览图 = 挂载到某个目录(mount);顾客只认区域名 = 统一的目录树(/data)。
所以这条链不是「Linux 故意绕圈子」,而是把一件大事拆成四件各管一段的小事:分区管「切多大」,文件系统管「怎么存、怎么找」,挂载管「怎么接进来」,目录树管「用户怎么记」。拆开以后,任何一段都能单独换掉——这才是后面所有命令存在的理由。
但这张图还只是「名字」。比喻必须能落到实体上——否则命令永远靠背。下面把五层逐一换成系统里真实存在的东西:叫什么、在哪、用什么命令能亲眼看见。
| 层 | 生活比喻 | Linux 里对应的真实概念(实体) | 怎么亲眼看到它 |
|---|---|---|---|
| ① 块设备 | 毛坯仓库 | 块设备文件 /dev/sdb(主次设备号 8:16),由内核的块设备驱动提供,在 /sys/block/sdb/ 下有自己的目录树。它只会「按块读写」,没有文件、没有目录、没有权限 |
lsblk -d(TYPE 列 = disk)ls -l /dev/sdb(行首是 b) |
| ② 分区 | 隔墙 + 平面图 | 分区表(MBR 占第 0 扇区的 512 字节;GPT 用前 34 个扇区且首尾各存一份)+ 分区设备 /dev/sdb1。注意:分区设备并没有把盘「切开」,它只是把「起始 LBA + 扇区数」包成一个可访问的窗口 |
fdisk -l /dev/sdb(看 Start / Sectors)lsblk(TYPE 列 = part) |
| ③ 文件系统 | 货架 + 编号 + 台账 | mkfs 写进分区的那一整套元数据:超级块(总账封面)、块位图 / inode 位图(哪格空着)、inode 表(每个文件的编号卡)、数据块(货位)、目录项(名字 → 编号的索引)。ext4 / xfs 只是这套结构的两种不同排版 | lsblk -f(FSTYPE 列)dumpe2fs -h /dev/sdb1(ext4 看超级块)xfs_info /dev/sdb1(xfs) |
| ④ 挂载 | 挂门牌 + 接进导览图 | 内核里的一张 mount 表:一条记录 = 设备 + 挂载点 + 文件系统类型 + 挂载选项。它把某个文件系统的「根」绑定到目录树里的一个 dentry(挂载点),路径解析走到这里就「跳」进那个文件系统 | findmntcat /proc/self/mountinfodf -hT |
| ⑤ 目录树 | 顾客只认区域名 | 唯一的根 / 与 VFS 的统一命名空间:路径解析(namei)在跨文件系统时透明拼接。所以你写下 /data/report.txt 时,内核可能已经穿过两块盘、一个 LVM、一个 RAID |
findmnt --target /data(看这条路径落在哪个设备上)stat -f /data |
/data 一定是某个分区;其实 LVM 的逻辑卷、RAID 阵列、甚至网络存储,都能挂成 /data,路径和物理盘从来不是一一对应。下面六张卡,每个概念都按同一个顺序讲:说人话(不用术语的一句话)→ 打个比方(生活里对应的东西)→ 为什么有这层(如果没有它会出什么事)→ 术语对照(考试和文档里的正式叫法)。
说人话在内核眼里,一块硬盘就是一大片能按格子读写的地方:告诉它「读第 1024 号格子」,它就把那 4KB 内容给你。
打个比方一整栋还没隔间的毛坯仓库:门开着、地是平的、能往里搬东西,但没有房间、没有编号、没有台账。
为什么有这层因为程序不该关心「你的盘是三星还是西数、插在哪个口」。内核把它统一成 /dev/sdX 一个文件,读写硬盘就跟读写文件一样;换硬件不用改一行程序。
术语对照:命名 sda/sdb(SATA/SCSI/USB)、vda(虚拟机)、nvme0n1(NVMe 固态);分区在名字后加序号。用 lsblk 看,TYPE 列 = disk。
说人话一张贴在磁盘最开头的小纸条,上面写着「第 0~100G 归 A,第 100~200G 归 B」。
打个比方在毛坯仓库里砌隔墙,再在门口贴一张平面图。墙让人各占一块,平面图让后来的人知道哪块是谁的。
为什么有这层因为一块盘要同时装系统和数据,必须划清边界:重装系统只格式化系统那一间,数据那间不受影响;某个目录写爆了,也只撑爆自己那间,不会拖死整块盘。
术语对照:MBR 最多 4 主分区、单盘 ≤2TB;GPT 可 128 分区、容量几乎不限、有备份表。换分区表 = 清空数据。TYPE 列 = part。
说人话给这段空间建一套台账:每个文件叫什么、多大、内容放在哪几块,全记下来,于是你能用「名字」找东西。
打个比方在隔好的房间里摆货架、贴编号、做账本。没有货架,货只能堆在地上——想找一件就得翻遍全场。
为什么有这层因为磁盘只会「读第 N 块」,它根本不认识「a.txt」。文件系统负责把「名字 / 目录」翻译成「块号」,顺便管权限、碎片、配额、断电后的修复。没有它,你就得自己记「我的数据在第 58712 块」。
术语对照:xfs / ext4 / vfat;三大件 = 超级块(全局信息)、inode(每个文件的元数据)、数据块(内容)。FSTYPE 列空 = 还没格式化。
说人话把某个准备好文件系统的分区,「接」到目录树的某个位置上,从此走这个目录就等于走进那块盘。
打个比方给仓库挂门牌,并把门牌登记进市场总导览图。没挂门牌的仓库,顾客永远找不到——东西在里面也等于不存在。
为什么有这层因为 Linux 只有一棵目录树,没有盘符这回事。挂载把「物理盘」和「路径」解耦:/home 可以从旧盘搬到新盘,用户的路径一个字都不用改;U 盘插上挂到 /media/xx 就出现了。
术语对照:挂载点必须是已存在目录;目录原有内容会被遮住,卸载后回来(所以挂载点通常选空目录)。开机自动挂载写在 /etc/fstab。
说人话内存不够用时,把暂时用不到的内存内容先挪到磁盘上放着,等要用再换回来(代价是慢)。
打个比方书桌放不下的资料先塞进抽屉。桌上永远只留正在看的,抽屉当「临时仓库」。
为什么有这层因为内存一旦耗尽,内核会启动 OOM killer 直接杀掉进程(可能杀掉你的数据库)。有 swap 就能先缓一缓,把不活跃的页面挤出去。
术语对照:swap 不是文件系统,用 mkswap 初始化、swapon 启用;fdisk 里分区类型要改成 82。查看用 swapon --show / free -h。
说人话一个文件系统有两份额度:能装多少「斤货」(块容量),和能贴多少「张标签」(inode 个数)。
打个比方货架还空着一大半,但标签用完了——新货照样上不了架,因为没法登记。
为什么有这层因为每个文件都必须占一个 inode(记录元数据)。小文件一多(邮件队列、缓存、日志碎片),容量还剩很多却先报「No space left on device」——这不是 bug,是另一份额度用完了。
术语对照:df -h 看块容量,df -i 看 inode;df -i 接近 100% 时,要么删小文件,要么重建文件系统调大 inode 比例。
这些比喻凭什么成立?把每个「零件」拆到字节级看
比喻不是修辞,而是同构:如果仓库里的某样东西,在磁盘上也能找到干同一件事的结构,这个比喻才算站得住。下面逐层拆开——重点看第 ③ 层,那也是学生最容易「听懂了但没真懂」的一层。
/dev/sdb 是一个块设备文件,open/read/write 就是「往盘上搬东西」。为什么等价:仓库只能整车进出,你没法从中间抠走一件——磁盘也一样,内核只允许整块(512B / 4K)读写,改 1 个字节也要「读整块 → 改 → 写回」。
testdisk 能恢复分区的原理。
55AA;GPT 则在首尾各存一份完整分区项表。为什么等价:图没了墙还在,但没人知道墙里归谁——记录(元数据)比实体更容易丢,所以 GPT 要留备份。
/dev/sdb1 只是内核按「起始 LBA + 长度」造出来的一个窗口设备。为什么等价:隔墙并没有真的把地搬走一块,只是从此只从这扇门进出。
mkfs这一层最能说明「为什么不是随便打个比方」ls -i 可见),里面记大小、权限、时间戳、链接数,以及「内容在哪几个块」的指针。为什么等价:编号卡上写「这票货 3 箱,箱号 8812/8813/8814」,但货不放在卡上——inode 也不存文件内容,只存「去哪找」。
文件名 → inode 号 的表。为什么等价:查台账 = 用名字换编号。关键推论:inode 里没有文件名,所以 mv 改名只是改台账那一行,数据块一格都没动——这就是改名「瞬间完成」的原因。
wrong fs type。
findmnt 看到)。为什么等价:门牌不属于仓库本体。关键推论:mount 一个字节都不写盘,只改内核内存里的映射——所以重启就没了,必须写 /etc/fstab。
umount 后回来。为什么等价:门牌挂上去,墙上原来的字被盖住了,但墙没拆——所以挂载点要选空目录,否则「文件像丢了」。
/data/report.txt,由 VFS 逐级解析。为什么等价:顾客只报区域名,管理员负责换算成位置——用户敲路径,内核负责换算成「哪块盘、哪个 inode、哪个块」。
/data 从旧盘迁到新盘 / 新 LVM,只需改 mount 表(或 fstab + 重启),程序里所有路径一个字不用改。为什么等价:水果区换了老板,导览图上还是「水果区」三个字。
mount 是内核内存里的映射,而且可以有多个视图(容器);④ 市场只有一个入口,Linux 的 / 可以被 chroot、容器「换一个根」。比喻帮你建立直觉,机制才决定你能不能排错。「文件系统是抽象层」这句话最容易让人似懂非懂。破解办法不是再讲一遍原理,而是给你 10 个能亲手复现的现象——每个现象都只在某个结构被用满、被改写、或者被跳过时才会出现。看完结构图再去敲命令,现象和结构就对上了。
因为目录也是文件。它同样占一个 inode,还至少占一个数据块——这个块里存的就是那张「文件名 → inode 号」的台账。
分配的最小单位是块,不是字节。不足一块也独占一整块(默认 4 KB)。这就是 ls -l 和 du 经常对不上的第一个原因。
稀疏文件:inode 里记了「大小 = 1 GB」,但一个块都没分配,位图里对应的位还是空。读它得到全 0,因为内核把「没分配的块」直接当 0 返回。
这就是硬链接:台账里多写了一行,指向同一张编号卡。删掉其中一个名字只是链接数 −1,减到 0 才真正回收块——这条现象直接证明「文件名不在 inode 里」。
同分区改名只改台账:两个目录项换个名字,数据块一格没动。而 cp 要把内容真搬一遍。跨分区 mv 例外——那其实是「复制 + 删除」,一样慢。
写一个文件要同时拿两份额度:1 个 inode + 若干块。小文件堆积(缓存、邮件、日志碎片)先把 inode 用光,于是容量空着也报 No space left on device。
还有进程开着这个文件。文件被删的只是名字,inode 引用数不为 0,块就不释放。重跑服务(或清空那个 fd)后空间才回来——这也是「删了日志、磁盘不降」的元凶。
没有。mkfs 只重写左侧那几格元数据,数据区一个字节没动,写进去的特征串原地还在(完整复现见下方实验 B)。所以格式化 ≠ 销毁;反过来卖旧盘前必须用 dd if=/dev/urandom 覆写。
靠日志(journal / log)。改数据前先写一条「我打算改什么」到日志区,改完才标记完成。掉电后挂载时重放日志,把做了一半的操作补完或撤销。
真的。xfs 只提供在线扩容,要缩小只能备份、重建、再灌回去;ext4 可以 resize2fs 缩。选型口诀:以后可能要缩 → ext4;只扩不缩 → xfs。
其中 04 和 08 建议现场敲一遍——它们最能说明「货架 / 编号卡 / 台账」这套比喻不是随口打的比方。
mkdir -p /data/lab && cd /data/lab
echo "hello" > a.txt
ln a.txt b.txt # 建硬链接:台账里加一行,指向同一张编号卡
ls -li # -i 显示 inode 号,-l 看链接数
# 131081 -rw-r--r-- 2 root root 6 Mar 12 10:00 a.txt
# 131081 -rw-r--r-- 2 root root 6 Mar 12 10:00 b.txt
# ↑ 同一个 inode 号 ↑ 链接数都是 2
rm a.txt # 只删掉「a.txt」这一行台账
ls -li
# 131081 -rw-r--r-- 1 root root 6 Mar 12 10:00 b.txt
# ↑ inode 没变,链接数变成 1,内容一个字没少
stat -c 'inode=%i 链接=%h 大小=%s' b.txt
# inode=131081 链接=1 大小=6# ① 往测试分区第 100 MB 处写一个特征串
echo "WENXUE-MAGIC-2026" | dd of=/dev/sdb1 bs=1M seek=100 conv=fsync
# ② 格式化之前,先在原位置找到它
dd if=/dev/sdb1 bs=1M skip=100 count=1 2>/dev/null | strings | grep WENXUE
# WENXUE-MAGIC-2026 ← 数据在这里(偏移 100 MB 处)
mkfs.ext4 -F /dev/sdb1 # 重新格式化
# ③ 格式化之后,再找一次
dd if=/dev/sdb1 bs=1M skip=100 count=1 2>/dev/null | strings | grep WENXUE
# WENXUE-MAGIC-2026 ← 它还在原地!普通分区是「一块盘切几段」。如果想让多块盘更安全(坏一块不丢数据)或更弹性(空间不够随时扩),就要在「分区」和「文件系统」之间插一层:软 RAID 或 LVM。它们最终都表现为一个块设备(/dev/md0 或 /dev/vg0/lv0),后面的格式化、挂载完全一样。
软 RAID = 复印机。说人话:把好几块盘当成一块用,同一份数据同时写进多块盘(或者分摊写、另存校验),坏掉一块还能把内容算回来。打个比方:重要合同复印两份、放两个抽屉,丢一个抽屉不心疼。为什么要有它:单块盘什么时候坏是概率问题,硬盘坏是常态而不是意外;用便宜的盘堆出「不宕机」,比买一块贵盘便宜得多。
LVM = 水库。说人话:先把几块盘倒进一个大池子,再从池子里按需「切」出任意大小的卷。打个比方:散装水库随时按瓶装水灌,比分区分装灵活。为什么要有它:分区是「一锤子买卖」——划多大就多大,想改要卸载、甚至重装;LVM 把「容量怎么分」这件事从「装机时」推迟到「用的时候」,不够了加盘扩池再切,业务不停。
那它们为什么正好插在「分区」和「文件系统」之间?
因为文件系统只认一件事:给我一块能读写的块设备。RAID 把自己伪装成 /dev/md0,LVM 把自己伪装成 /dev/vg0/lv0——在上面看,它们和 /dev/sdb1 长得一样。所以你能照常 mkfs、照常 mount,一行代码都不用改。这就是分层的真正价值:只要接口不变,中间随便加东西。
讲「分层好」最没用的说法就是「这样比较清晰」。真正让人信服的问法是:如果拿掉这一层,会发生什么?下面这张图就干这件事——假设你真的「删掉」某一层,看看代价是什么。
顺着这个思路,就能回答「为什么要这样分层」的三个真实理由:
ext4 换成 xfs 不用重新分区;机械盘换成固态盘不用改程序;甚至把底下的盘换成 RAID,上面的文件系统毫不知情。因为接口没变。
盘 → RAID 1 → LVM → xfs → /data,五层叠起来照样工作。这是分层最实用的红利:没人需要为你发明一个「RAID+LVM 专用文件系统」。
/var 日志写爆不会拖死 /;某个学生配额超了不影响别人;一个分区误操作,别的分区还在。边界本身就是保护。
费曼技巧的第三步不是「再看一遍」,而是合上讲义,试着讲给别人听。卡住的地方,就是你理解的漏洞。下面三题,能顺畅讲完就说明这一章的地基打好了:
/data 报「空间不足」,你能说出删文件 / 加块盘 / 扩逻辑卷这三种做法,各自动的是哪一层吗?学命令最怕「不知道什么时候用」。先记住这张对照表,后面每条命令的细节再按需展开。
| 我要解决的问题 | 第一步看 | 动手命令 | 对应小节 |
|---|---|---|---|
| 机器上有几块盘?分区和文件系统是什么? | lsblk -f | blkid 看 UUID | 5.1.1 |
| 哪个目录快满了?还剩多少空间? | df -h | du -sh /* 定位大户 | 5.1.1 |
| 新加了一块盘,要切成一个分区 | lsblk | fdisk / parted | 5.1.2 |
| 分区建好了,但还是用不了 | —— | mkfs.xfs 格式化 | 5.1.3 |
| 格式化好了,怎么访问它? | —— | mount + 写 /etc/fstab | 5.1.4 |
| 限制某个学生只能用 200M | xfs_quota report | xfs_quota limit | 5.2 |
| 一块盘坏了不能丢数据 | cat /proc/mdstat | mdadm --create | 5.3 |
| 空间不够,想在线扩容 | vgs / lvs | vgextend + lvextend | 5.4 |
fdisk 里按 w 保存、mkfs 格式化、mdadm --create 建阵列、pvcreate 初始化 PV。练习前先给虚拟机打快照;生产环境操作前先备份,并再三核对设备名(/dev/sdb 和 /dev/sda 一字之差,可能就是系统盘)。lsblk 而不是凭印象。w、mkfs、--create 这类「写入型」操作,先停下来读一遍提示。/etc/fstab 后,先用 mount -a 验证,没问题再重启。动手之前必须知道现状。四个命令分工不同:lsblk 看硬件与分区结构,blkid 看文件系统类型与 UUID,df 看已挂载文件系统的用量,du 看目录里谁在占空间。
列出所有块设备,以树状展示「磁盘 → 分区 → LVM/RAID」的从属关系。它读的是内核设备树,不需要挂载也能看。
lsblk 默认树状列表:名称、大小、类型、挂载点-f 增加 FSTYPE、LABEL、UUID(最常用)-p 显示完整设备路径(/dev/sdb1 而非 sdb1)-d 只显示整盘,不显示分区-o NAME,SIZE,TYPE,MOUNTPOINT 自选列-J 输出 JSON,便于脚本处理lsblk
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# vda 252:0 0 40G 0 disk ← 第一块虚拟盘,40G
# ├─vda1 252:1 0 1G 0 part /boot ← 分区1,挂到 /boot
# ├─vda2 252:2 0 39G 0 part ← 分区2,没直接挂载
# │ └─rl-root 253:0 0 37G 0 lvm / ← 它上面做了 LVM,根目录在这
# └─vda3 252:3 0 2G 0 part [SWAP] ← swap 分区
# sdb 8:16 0 10G 0 disk ← 新加的盘:没有分区
# └─sdb1 8:17 0 10G 0 part /data ← 已分好并挂载
lsblk -f
# NAME FSTYPE LABEL UUID MOUNTPOINT
# vda1 xfs a1b2c3d4-... /boot
# vda2 LVM2_member e5f6a7b8-...
# sdb1 xfs data 7c8d9e0f-... /data查看指定块设备的文件系统类型、UUID、LABEL。写 /etc/fstab 前用它拿 UUID——比 /dev/sdb1 稳定,插拔硬盘后设备名可能变,UUID 不变。
blkid 列出所有已格式化设备blkid /dev/sdb1 只看某分区blkid -s UUID -o value /dev/sdb1 只输出 UUID 值,便于复制lsblk -f 看结构 + 文件系统(推荐日常)blkid 看细节属性(UUID/LABEL)blkid /dev/sdb1
# /dev/sdb1: LABEL="data" UUID="7c8d9e0f-1234-..." TYPE="xfs"
# 只取 UUID,方便直接粘进 fstab
blkid -s UUID -o value /dev/sdb1
# 7c8d9e0f-1234-...查看已挂载文件系统的总容量、已用、可用、使用率。它统计的是文件系统级别的总量,不是某个目录。
df -h 人类可读单位(G/M)df -T 多显示文件系统类型df -i 看 inode 使用情况(文件数)df -h /data 只看某个挂载点df -hT
# Filesystem Type Size Used Avail Use% Mounted on
# /dev/vda2 xfs 37G 9.8G 27G 27% /
# /dev/sdb1 xfs 10G 1.2G 8.8G 12% /data
df -i
# Filesystem Inodes IUsed IFree IUse% Mounted on
# /dev/sdb1 6553600 120000 6433600 2% /data ← inode 也要看逐个目录累加统计实际占用,用来找出「谁把空间吃掉了」。和 df 的区别:df 看总量(问文件系统),du 看明细(爬目录树)。
du -sh /data 汇总该目录总大小du -h --max-depth=1 /data 只看第一层子目录du -ah /data | sort -rh | head 找最大的文件-x 不跨文件系统(避免统计到别处)lsof +L1 找「已删除但仍被占用」的文件du -sh /var/log # /var/log 总共占多少
du -h --max-depth=1 /data # /data 下每个子目录各占多少
du -ah /data | sort -rh | head -5 # 最大的 5 个文件/目录分区 = 在盘上划线,告诉系统「这一段归谁用」。划线前先选分区表:老设备用 MBR,新设备与大容量盘用 GPT。
| 对比项 | MBR(msdos) | GPT |
|---|---|---|
| 最大分区数 | 4 个主分区(或 3 主 + 扩展分区再分逻辑分区) | 默认 128 个 |
| 单盘最大容量 | 2 TB | 极大(9.4 ZB 级别) |
| 分区表备份 | 无,损坏难恢复 | 有备份表 + CRC 校验,更抗损坏 |
| 启动方式 | 传统 BIOS | UEFI(现代机器) |
| 常用工具 | fdisk | parted / gdisk |
交互式分区工具,默认 MBR。进入后是一问一答的菜单,最后按 w 才真正写入磁盘——在此之前都可以 q 退出放弃。
fdisk -l /dev/sdb 不进交互,直接列出n 新建分区(选主/扩展、分区号、起止扇区或大小)d 删除分区p 打印当前分区表(只是预览)t 改分区类型:82=swap,83=Linux,8e=LVMw 写入并退出(此刻才生效!)q 不保存退出fdisk /dev/sdbn → p → 分区号回车 → 起始回车 → 大小 +10Gp 检查无误w 保存partprobe /dev/sdb 让内核重读(有时需要)fdisk /dev/sdb
# 欢迎使用 fdisk...
# 命令(输入 m 获取帮助):n ← 新建
# 分区类型: p(主) e(扩展) p (MBR 最多 4 个主分区)
# 分区号 (1-4, 默认 1): 1
# 第一个扇区 (默认 2048): 回车
# 最后一个扇区, +sectors 或 +size: +10G (分 10G)
# 创建了一个新分区 1,类型为 Linux,大小 10 GiB
# 命令:p ← 先预览
# 命令:w ← 确认写入(不可撤销)
# The partition table has been altered.
lsblk /dev/sdb
# sdb 10G disk
# └─sdb1 10G part ← 分区已出现,但还没有文件系统(FSTYPE 空)支持 GPT,可一条命令完成、也可交互。比 fdisk 更适合 2TB 以上磁盘和脚本化操作。注意:mklabel 会重建分区表,原分区全没了。
parted /dev/sdb 进入交互mklabel gpt 建 GPT 分区表(清空原有分区)mkpart primary xfs 1MiB 10GiB 建 1M~10G 的分区print 查看;quit 退出parted /dev/sdb mklabel gptparted /dev/sdb mkpart primary xfs 1MiB 10GiBparted /dev/sdb printparted -s 关闭交互提示parted /dev/sdb mklabel gpt
# 警告:会破坏现有分区表 —— 新盘可以,旧盘务必确认
parted /dev/sdb mkpart primary xfs 1MiB 500GiB
# 从 1MiB 开始(留出对齐空间),到 500GiB
parted /dev/sdb print
# Number Start End Size File system Name Flags
# 1 1049kB 537GB 500GB primarypartprobe /dev/sdb;仍不行就 partx -u /dev/sdb,或卸载后重新扫描。格式化 = 在分区上建文件系统,相当于给空地盖房子:划分超级块、inode 区、数据区。没格式化的分区,mount 会报「wrong fs type」。
按文件系统类型格式化。mkfs 是总入口,mkfs -t xfs 与 mkfs.xfs 等价。格式化会清空该分区全部数据。
mkfs.xfs /dev/sdb1 格式化为 xfs(RHEL 默认)mkfs.ext4 /dev/sdb1 格式化为 ext4mkfs.xfs -L data /dev/sdb1 加卷标 data,方便识别mkfs.xfs -f /dev/sdb1 强制覆盖已有文件系统mkfs.xfs -b size=4096 指定块大小(一般默认即可)xfs_info /dev/sdb1 看 xfs 信息tune2fs -l /dev/sdb1 看 ext4 信息blkid /dev/sdb1 确认 TYPE 变了| 对比项 | xfs | ext4 |
|---|---|---|
| 默认发行版 | RHEL / CentOS / Rocky 8+、Anolis | Ubuntu / Debian 常见 |
| 大文件性能 | 强(并发、大文件友好) | 好 |
| 缩容 | 不支持缩容(只能扩) | 支持缩容(需先卸载、检查) |
| 扩容命令 | xfs_growfs /挂载点 | resize2fs /dev/xxx |
| 适用场景 | 服务器、数据库、生产默认 | 通用、需要缩容的实验环境 |
mkfs.xfs -L data /dev/sdb1
# meta-data=/dev/sdb1 isize=512 agcount=4 ...
# data = bsize=4096 blocks=2621440 ...
# 出现 "data" 卷标与 blocks 信息 = 成功
blkid /dev/sdb1
# /dev/sdb1: LABEL="data" UUID="7c8d9e0f-..." TYPE="xfs" ← TYPE 从空变成 xfs把分区做成交换空间并启用。swap 不是文件系统,不挂载到目录,而是被内核当「虚拟内存」使用。
fdisk /dev/sdb → t → 82 改类型mkswap /dev/sdb2 初始化交换分区swapon /dev/sdb2 启用swapon --show / free -h 验证UUID=xxx none swap defaults 0 0swapoff /dev/sdb2mkswap /dev/sdb2
# Setting up swapspace version 1, size = 2 GiB
swapon /dev/sdb2
free -h
# total used free shared buff/cache available
# Swap: 4.0G 0B 4.0G ← 增加了 2G格式化完的分区仍然「没门牌」。挂载就是把文件系统接到目录树上的某个目录,之后访问这个目录就等于访问那块盘。
临时挂载 / 卸载。重启后失效——要永久生效必须写 /etc/fstab。
mount /dev/sdb1 /data 挂载到 /datamount -t xfs /dev/sdb1 /data 显式指定类型(一般自动识别)mount -o ro /dev/sdb1 /data 只读挂载mount -o remount,rw /data 重新挂载并改为可写mount -a 按 fstab 挂载所有(改完 fstab 先跑它验证)findmnt /data 查看某挂载点详情umount /data 或 umount /dev/sdb1target is busy:fuser -vm /data 看谁在用umount -l /data 延迟卸载(不推荐,治标)cd / 退出该目录再卸载mkdir -p /data # 挂载点必须已存在
mount /dev/sdb1 /data # 挂载
df -h /data
# Filesystem Size Used Avail Use% Mounted on
# /dev/sdb1 10G 0 10G 0% /data ← 已生效
umount /data # 卸载(卸载后目录恢复为空)开机自动挂载的配置文件,每行 6 个字段。写错可能导致系统启动失败,改完务必 mount -a 验证。
UUID=xxxx,不推荐 /dev/sdb1xfs/ext4/swapdefaults;加固可 defaults,nofail01,其它 2 或 0blkid -s UUID -o value /dev/sdb1 拿 UUIDUUID=... /data xfs defaults,nofail 0 0mount -a 无报错 = 配置正确reboot 验证真能自动挂载# ① 取 UUID
blkid -s UUID -o value /dev/sdb1
# 7c8d9e0f-1234-5678-90ab-cdef12345678
# ② 追加到 fstab(>> 是追加,> 会覆盖整个文件,千万别写错)
echo 'UUID=7c8d9e0f-1234-5678-90ab-cdef12345678 /data xfs defaults,nofail 0 0' >> /etc/fstab
# ③ 先验证语法,再重启
mount -a
findmnt /data
# TARGET SOURCE FSTYPE OPTIONS
# /data /dev/sdb1 xfs rw,relatime,... ← 成功e 编辑内核参数,在 ro 后加 rd.break(或进救援模式),mount -o remount,rw / 后注释掉错误行,再重启。所以强调:改完 fstab 一定先 mount -a。一台服务器给全班用,如果不管,一个人就能把盘塞满。配额(quota)限制某个用户/组在一个文件系统上能用的「容量(block)」和「文件数(inode)」。
| 概念 | 含义 | 对应的限制参数 |
|---|---|---|
| 软限(soft) | 可以短暂超过,超过后进入「宽限期」,到期必须降下来 | bsoft(容量)、isoft(文件数) |
| 硬限(hard) | 绝对上限,一旦达到就写不进去 | bhard、ihard |
| 宽限期(grace) | 软限到期前的缓冲时间,默认 7 天 | xfs_quota ... timer |
| block 配额 | 按容量算(单位 K/M/G) | bsoft/bhard |
| inode 配额 | 按文件个数算(防止海量小文件) | isoft/ihard |
为什么两种都要限:只限容量,用户可以建几百万个空文件把 inode 耗尽;只限文件数,用户可以写一个超大文件把容量占满。生产上通常两个一起设。
xfs 文件系统的配额管理工具。前提:挂载时必须带配额选项,否则命令会报「Quota not enabled」。
defaults,uquota(用户配额)gquota,目录配额用 prjquotamount -o remount,uquota /dataxfs_quota -x -c 'limit bsoft=100m bhard=120m isoft=800 ihard=1000 stu01' /dataxfs_quota -x -c 'report -h' /data 看全部用户xfs_quota -x -c 'quota -u stu01' /data 看单人xfs_quota -x -c 'timer -u 3d stu01' /data 改宽限期xfs_quota -x -c 'off -u' /data 临时关闭# ① 确认挂载选项里有 uquota
findmnt -o TARGET,OPTIONS /data
# /data /dev/sdb1 xfs rw,relatime,attr2,inode64,uquota ← 有 uquota 才可继续
# ② 设置配额:容量软限 100M、硬限 120M;文件数软限 800、硬限 1000
xfs_quota -x -c 'limit bsoft=100m bhard=120m isoft=800 ihard=1000 stu01' /data
# ③ 查看
xfs_quota -x -c 'report -h' /data
# User quota on /data (/dev/sdb1)
# Blocks Inodes
# User ID Used Soft Hard Warn/Grace Used Soft Hard Warn
# stu01 1001 0 100M 120M 00:00 0 800 1000 00:00# 切到 stu01,往 /data 写 130M(超过硬限 120M)
su - stu01
dd if=/dev/zero of=/data/big.bin bs=1M count=130
# dd: error writing '/data/big.bin': Disk quota exceeded ← 硬限拦住了
ls -lh /data/big.bin
# -rw-r--r-- 1 stu01 stu01 120M ... ← 只能写到 120Mquotacheck -cum /data → quotaon /data → edquota -u stu01(交互编辑)或 setquota -u stu01 102400 122880 800 1000 /data。原理相同,工具不同。| 级别 | 最少盘数 | 容错能力 | 空间利用率 | 读写特点 | 典型场景 |
|---|---|---|---|---|---|
| RAID 0 条带 | 2 | 无(坏一块全丢) | 100% | 读写都快 | 临时数据、缓存(不怕丢) |
| RAID 1 镜像 | 2 | 坏 1 块 | 50% | 读快、写稍慢 | 系统盘、小容量高可靠 |
| RAID 5 校验 | 3 | 坏 1 块 | (n-1)/n | 读快、写有校验开销 | 文件服务器、Web 存储 |
| RAID 6 双校验 | 4 | 坏 2 块 | (n-2)/n | 写更慢 | 大容量归档、重要数据 |
| RAID 10 镜像+条带 | 4 | 每组坏 1 块 | 50% | 读写都快 | 数据库等高 IO 场景 |
一句话选型:要安全选 1 或 10,要容量与性能折中选 5,要极致可靠选 6。RAID 不是备份——它防的是「硬盘坏」,不防误删、病毒、火灾,重要数据仍要另做备份。
Linux 软 RAID 管理工具(md = multiple devices)。建好后是一个新的块设备 /dev/md0,后续格式化、挂载与普通分区完全一样。
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc 建 RAID 1--spare-devices=1 /dev/sdd 顺带指定热备盘cat /proc/mdstat 看同步进度(最快)mdadm -D /dev/md0 看阵列详情mdadm --manage /dev/md0 --fail /dev/sdc 模拟坏盘--remove 移除坏盘;--add 加新盘重建mdadm --detail --scan >> /etc/mdadm.conf 记录配置mdadm --stop /dev/md0 停止阵列# ① 建阵列(两块盘做镜像)
mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# mdadm: array /dev/md0 started. ← 开始在后台同步
# ② 看同步进度(RAID 1 初次同步可能几分钟)
cat /proc/mdstat
# md0 : active raid1 sdc[1] sdb[0]
# 10483712 blocks super 1.2 [2/2] [UU] ← [UU] 两块都在线
# [=>...................] resync = 5.2%
# ③ 格式化为 xfs 并挂载(和普通分区一样)
mkfs.xfs /dev/md0
mkdir -p /mnt/raid
mount /dev/md0 /mnt/raid
df -h /mnt/raid# 模拟 /dev/sdc 故障
mdadm --manage /dev/md0 --fail /dev/sdc
cat /proc/mdstat
# md0 : active raid1 sdc[1](F) sdb[0]
# [2/1] [_U] ← F = Failed,但阵列仍在跑,数据可读
# 移除坏盘,换上新盘 /dev/sdd 并重建
mdadm --manage /dev/md0 --remove /dev/sdc
mdadm --manage /dev/md0 --add /dev/sdd
cat /proc/mdstat # 会看到 recovery 进度,回到 [UU] 即修复完成# ① 记录阵列配置,重启后才能自动组装
mdadm --detail --scan >> /etc/mdadm.conf
# ② fstab 加挂载(用 md0 的 UUID)
blkid -s UUID -o value /dev/md0
echo 'UUID=xxxx-xxxx /mnt/raid xfs defaults,nofail 0 0' >> /etc/fstab
mount -aLVM 把「磁盘」和「分区」解耦:先把盘登记成 PV(物理卷),再把多个 PV 汇成 VG(卷组,一个空间池),最后从池子里切出 LV(逻辑卷)当分区用。池子里还有空间,就能随时给 LV 扩;池子不够,就往 VG 里加盘。
用 pvcreate 把整盘或分区「登记」为 PV,会在设备头部写入 LVM 元数据。登记会破坏原有数据。
多个 PV 组成的大池子,用 vgcreate 创建、vgextend 加盘。空间以 PE(物理扩展块,默认 4MiB)为单位管理。
从 VG 切出来的一块,用 lvcreate 创建,设备路径是 /dev/vg名/lv名。对上层来说它就是一个分区。
命令链是一条直线:PV → VG → LV → mkfs → mount。中途可用 pvs/vgs/lvs 随时查看三层状态。
pvcreate /dev/sdb /dev/sdc 两块盘都登记为 PVvgcreate vg0 /dev/sdb /dev/sdc 组成卷组 vg0lvcreate -L 10G -n lv0 vg0 切 10G 的 lv0lvcreate -l 100%FREE -n lv1 vg0 剩余全给 lv1mkfs.xfs /dev/vg0/lv0 格式化pvs / vgs / lvs 三行速览pvdisplay / vgdisplay / lvdisplay 详情vgs 看 VFree(池子还剩多少)# ① 登记物理卷
pvcreate /dev/sdb /dev/sdc
# Physical volume "/dev/sdb" successfully created
# ② 组成卷组(池子)
vgcreate vg0 /dev/sdb /dev/sdc
# Volume group "vg0" successfully created
vgs
# VG #PV #LV #SN Attr VSize VFree
# vg0 2 0 0 wz--n- 19.99g 19.99g ← 池子约 20G 可用
# ③ 切出 10G 逻辑卷
lvcreate -L 10G -n lv0 vg0
# Logical volume "lv0" created.
lvs
# LV VG Attr LSize Pool Origin Data% Meta% Move
# lv0 vg0 -wi-a----- 10.00g
# ④ 格式化并挂载
mkfs.xfs /dev/vg0/lv0
mkdir -p /data
mount /dev/vg0/lv0 /data
df -h /data空间不够时的标准动作:池子不够先加盘(vgextend),池子够就直接扩逻辑卷(lvextend),最后一定要扩文件系统。少做最后一步,df 就不会变——这是新手最常踩的坑。
扩容三步走。lvextend -r 可以顺便自动扩文件系统,省一步。
vgextend vg0 /dev/sdd 给池子加一块新盘lvextend -L +5G /dev/vg0/lv0 给 lv0 加 5Glvextend -l +100%FREE /dev/vg0/lv0 把池子剩余全给它lvextend -r -L +5G ... 加 -r 自动扩文件系统xfs_growfs /data(对挂载点操作,必须已挂载)resize2fs /dev/vg0/lv0(对设备操作)df -h /data 容量变大才算成功# ① 池子里还有空间,直接扩卷 +5G
lvextend -L +5G /dev/vg0/lv0
# Size of logical volume vg0/lv0 changed from 10.00 GiB to 15.00 GiB
# ② 扩文件系统(xfs 必须做这步,否则 df 还是 10G)
xfs_growfs /data
# data blocks changed from 2621440 to 3932160
# ③ 验证
df -h /data
# Filesystem Size Used Avail Use% Mounted on
# /dev/mapper/vg0-lv0 15G 1.2G 14G 9% /data ← 变成 15Gvgextend vg0 /dev/sdd # 把新盘 sdd 加入池子
vgs # 确认 VFree 变大
lvextend -l +100%FREE /dev/vg0/lv0 # 剩余空间全给 lv0
xfs_growfs /data # 扩文件系统
df -h /data| 现象 | 定位命令 | 原因与处理 |
|---|---|---|
| 磁盘满了,但 du 找不到大文件 | df -h → du -sh /* → lsof +L1 | 文件被删除但仍被进程占用。找到进程后重启对应服务,空间才会释放。 |
容量没满却报 No space left on device | df -i | inode 耗尽(小文件太多)。清理缓存目录/邮件队列,或重新格式化时增大 inode 数。 |
umount 报 target is busy | fuser -vm /data、lsof +D /data | 有进程或当前 shell 在该目录。退出目录、结束占用进程后再卸载。 |
| fstab 写错,系统起不来 | 启动时看报错、进救援模式 | mount -o remount,rw / 后注释错误行;以后改完先 mount -a 验证。 |
分区建好但 /dev/sdb1 不存在 | lsblk、dmesg | tail | 内核未重读分区表。执行 partprobe /dev/sdb。 |
df 看整体、再 du 下钻、然后 lsblk -f 看结构、最后 dmesg | tail 看内核报错。四条命令覆盖 80% 的磁盘问题。lsblk -f 画出当前机器的磁盘结构(哪些盘、几个分区、各自文件系统与挂载点),再用 df -hT 与 df -i 说明哪个分区最该关注。/dev/sdb 分区(10G)→ 格式化为 xfs → 挂到 /data → 用 UUID 写进 /etc/fstab → mount -a 验证 → 重启确认自动挂载。stu01 在 /data 上设 xfs 配额:容量软限 200M、硬限 250M,文件数硬限 1000;用 dd 写 300M 验证被拦截,并截图 xfs_quota report。/dev/sdb、/dev/sdc 建 RAID 1(/dev/md0),格式化挂载后,用 --fail 模拟一块盘损坏,观察 /proc/mdstat 的 [UU] → [_U] 变化,再换盘重建回 [UU]。/dev/sdb、/dev/sdc 做成 PV 聚成 vg0,切 10G 的 lv0 挂到 /data;再从 /dev/sdd 加盘进池子,在线扩到 15G,用 df -h 证明容量真的变了。磁盘管理操作有风险,务必在虚拟机快照后练习;mkfs / mdadm --create / pvcreate 会清空数据。每道题都要留下「命令 + 关键输出 + 一句解释」的实验记录。