今天中午有个同事跑过来找我,说测试机重启之后卡在了字符界面,没进系统。我远程一看,/etc/fstab 里挂了一项不存在的云盘,系统启动时找不到设备,直接落到了 emergency mode。这种问题我见过不止一次,每次都能撂倒好几个刚入门的人。借着这个事,我决定把 Linux 磁盘从创建、分区、挂载到 LVM 逻辑卷扩容的完整路径,重新梳理一遍。这篇文章适合刚上手 Linux 服务器的运维、做开发板系统调试的嵌入式工程师,以及经常要搭测试环境的后端朋友参考,内容不追求猎奇,全部是生产里能直接落地的操作。
1. 先看清家底:磁盘、分区、文件系统,这三个概念别混了
很多人上来就敲 fdisk /dev/sdb,但对这块盘在系统里到底处于什么状态,其实是模糊的。磁盘、分区、文件系统是三层完全不同的东西,混在一起想,后面遇到问题会特别拧巴。
磁盘是最底层的块设备,在 Linux 里通常表现为 /dev/sda、/dev/nvme0n1、/dev/vdb 这类名称。划分磁盘得到的区域叫分区,/dev/sda1、/dev/vdb2 就是分区设备。分区上还得建文件系统,比如 ext4、xfs,才能存文件。挂载其实是在文件系统和目录之间建立一个入口,让你通过 /data 这样的路径访问磁盘上的数据。
1.1 先摸清机器上现在挂着什么
拿到一台新机器,第一步不是分区,而是先看:
bash复制lsblk
这个命令会把系统里的磁盘、分区、挂载点、容量一股脑列出来,可读性比 fdisk -l 好得多。输出里会显示诸如 sda、sdb、nvme0n1 这样的磁盘设备,以及它们下面的分区和挂载点。没有挂载点的磁盘就是还没有被使用的,可以拿来规划。
再看块设备的唯一标识和文件系统类型:
bash复制blkid
blkid 输出的 UUID 后面在 fstab 里会用到。
1.2 分区表和分区工具的选择
分区表主要有 MBR 和 GPT 两种。MBR 对单盘容量支持到 2TB 左右,最多 4 个主分区,新环境尽量别碰。GPT 支持大容量、更多分区,是目前的主流。新建分区时可以用 fdisk,或者 parted。
bash复制fdisk /dev/sdb
进入交互界面后,输入 g 创建 GPT 分区表,然后 n 新建分区,w 保存退出。这里有个容易被忽略的点:如果用 fdisk 操作一块已经存在分区表的盘,并且分区是在其他系统或工具里做的,修改后一定要确认分区表已经重新读取,必要时重启或运行 partprobe。
1.3 文件系统决定了你后面能做什么
分区建好以后,需要格式化。常用的是 ext4 和 xfs:
bash复制mkfs.ext4 /dev/sdb1
# 或者
mkfs.xfs /dev/sdb1
很多生产环境偏爱 xfs,因为它在大文件、高并发场景下表现不错,Red Hat 系默认也是 xfs。但 xfs 有个特点必须记住:它不支持缩减。如果你有缩容需求,比如希望以后能动态地把空间调小,那 ext4 更合适。选文件系统不只是看性能,还要看你对后续运维动作的预期。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 挂载这一步,讲究比想象中多
分区建好、文件系统格式化之后,磁盘还无法直接用。你必须把它挂载到某个目录下,这个目录称为挂载点。
2.1 挂载点怎么选
常见做法是在根目录下建一个专门的数据目录,比如 /data、/opt,或者挂在 /mnt 下。系统目录像 /usr、/var 不要随便挂额外磁盘,否则容易和系统自带的数据混在一起,升级软件、写日志时会产生你意想不到的冲突。
code复制mkdir -p /data
mount /dev/sdb1 /data
挂载成功后,df -h 就能看到 /data 的容量和磁盘对应关系。挂载点必须是空目录,或者你确定可以覆盖原有内容的目录。挂到非空目录不会报错,但原目录里的文件会被暂时遮蔽,等卸载后才会重新出现,第一次用容易吓一跳。
2.2 挂载参数别乱省
mount 命令直接挂在生产盘时,我通常会带上一些参数:
bash复制mount -o defaults,noatime /dev/sdb1 /data
noatime 表示访问文件时不更新访问时间戳,可以明显减少磁盘写入,对数据库和日志类应用有一定帮助。defaults 是默认参数组合,包括 rw、suid、dev、exec、auto、nouser、async 等,绝大多数场景够用。还有 nodiratime 这类参数,现在内核多数已经默认覆盖。
2.3 用 findmnt 检查挂载关系
df -h 看的是容量,但mount 命令更多是看参数。更直观的是 findmnt:
bash复制findmnt /data
它会显示这个挂载点对应哪个设备、文件系统类型、挂载选项。排查问题时比 mount | grep 干净得多。
3. fstab 持久化:UUID、参数与启动故障的取舍
临时挂载只对当前运行状态有效,重启就没了。要让系统启动时自动挂载,必须写进 /etc/fstab。这一步是经典的重灾区,写错了轻则挂载不上,重则系统起不来。
3.1 fstab 的六个字段
code复制UUID=xxx /data xfs defaults,noatime 0 0
从左到右依次是:设备标识、挂载点、文件系统类型、挂载参数、是否 dump、是否 fsck。最后两列在多数场景下写 0 0 就行。系统启动时读取到这个文件的顺序在文件系统就绪之后,如果磁盘设备名变了或 UUID 对不上,启动阶段就会报错。
3.2 为什么设备名不靠谱
/dev/sdb 这种名字在系统重启后可能变成 /dev/sdc,尤其在有多块云盘、USB 盘、虚拟化环境里,设备枚举顺序并不稳定。而 UUID 是格式化时生成的文件系统唯一标识,基本不会变,所以 fstab 里我坚持用 UUID。
bash复制blkid /dev/sdb1
把输出里的 UUID="xxxx" 抄进 fstab,设备那列写 UUID=xxxx 而不是 /dev/sdb1。不要手动敲 UUID,容易抄错,建议用命令输出直接复制。
3.3 写完 fstab 别急着重启
这是新手的经典翻车点。改完 fstab 后直接重启,配置一错,系统进不了正常模式。正确做法是先用下面命令验证:
bash复制mount -a
mount -a 会重新读取 fstab 并挂载所有尚未挂载的条目。如果报错,说明配置有问题,当场就能看出来,而不是等重启后才后悔。我还习惯在 fstab 里给一些远程或可暂时缺失的挂载项加 nofail 参数:
code复制UUID=xxx /data xfs defaults,noatime,nofail 0 0
nofail 的意思是即使设备不存在,系统启动时也不会因为这个条目进入 emergency mode,最多就是目录空着。这对云盘、U盘、移动硬盘这类可能被拔掉的设备尤其重要。生产里,如果某个磁盘确实必须在线,那不加 nofail 反而是一种保障,启动失败好过带病运行,这个要根据场景权衡。
3.4 systemd 下的挂载单元
现在主流发行版都用 systemd,fstab 条目会被自动转换成挂载单元。nofail 在 systemd 里也有对应行为。如果 fstab 是某个可移动设备,还可以用 noauto 让系统启动时不自动挂载,需要使用的时候手动挂,避免插着盘开机时因为文件系统错误卡住启动过程。
4. 为什么绕不开 LVM:普通分区在扩容时的天花板
先来回答一个问题:如果只是把一块盘挂到目录下,不用 LVM 行不行?答案是可以,但真正运作一段时间之后,你就会发现普通分区在扩容这件事上非常难受。
4.1 扩容必须看分区表和相邻空间
传统分区扩容的逻辑是:这块分区后面必须有未分配的空闲空间,然后扩展分区、再扩展文件系统。如果分区后面顶着一堆其他分区,或者磁盘空间本来就满了,就只能加新盘、迁移数据、重新规划目录,过程非常痛苦。生产环境里给 /home 或 /var/log 扩容,很多时候不是你想扩就能扩的。
4.2 日志分区、数据库目录这类场景
典型场景是日志分区,每天写几个 GB,你没法提前算准三个月后的容量。如果当初没做 LVM,出现空间告警时你只能停机、插新盘、拷数据、改挂载,一整套动作下来至少大半天。但如果是 LVM,逻辑卷可以跨磁盘、跨分区,空间不够就加一块新盘,把它扩充进卷组,然后直接把逻辑卷加大,文件系统在线扩一下就行,整个过程服务可以不用停。
4.3 LVM 的抽象逻辑
LVM 的全称是 Logical Volume Manager,核心是三层抽象:PV(物理卷)、VG(卷组)、LV(逻辑卷)。
可以把磁盘当成几个水池,PV 就是把每个水池划归给一个总蓄水系统,VG 是这个蓄水系统的总容量,LV 是你真正接到每家每户的水管。水池不够了,往 VG 里再接一个水池,LV 这根水管能分到的水量就变大了。文件系统是建在 LV 上的,所以对用户来说,/data 的容量可以随 LV 的调整而变大。
理解这个抽象关系,后面所有命令都会变得顺理成章。
5. LVM 逻辑卷创建全流程:PV、VG、LV 三步走
从零手工创建 LVM 逻辑卷,操作本身不复杂,关键是要理解每一步在干什么。
5.1 初始化物理卷
假设有两块新盘 /dev/sdb、/dev/sdc,先在系统层面看到它们,然后初始化:
bash复制pvcreate /dev/sdb /dev/sdc
这里可以在整块磁盘上直接做,也可以先分区再对分区做。整盘做 PV 省事,但有些厂商的监控工具希望看到分区表,否则报警。如果要求分区,就先用 fdisk 把整块盘做成一个分区,再 pvcreate /dev/sdb1。
执行后可以用 pvs 看结果:
bash复制pvs
输出里 PV 一列就是物理卷,VG 列目前为空,因为还没加入卷组。
5.2 创建卷组
把两块 PV 合成一个 VG:
bash复制vgcreate data_vg /dev/sdb /dev/sdc
data_vg 是卷组名,自己起一个有意义的名字。创建完用 vgs 看总容量:
bash复制vgs
可以看到 VG 的总大小,以及剩余空间。PE(Physical Extent)是 LVM 分配空间的最小单位,默认 4MB,后面扩容时你不需要关心单个 PE,但看到 Total PE 和 Free PE 时能对上号就行。
5.3 创建逻辑卷并格式化
从卷组里划一块空间出来,比如 200GB:
bash复制lvcreate -L 200G -n data_lv data_vg
-n 是逻辑卷名,data_vg 是卷组名。创建后设备路径是 /dev/data_vg/data_lv。然后格式化:
bash复制mkfs.xfs /dev/data_vg/data_lv
挂载到 /data:
bash复制mkdir -p /data
mount /dev/data_vg/data_lv /data
要开机自动挂载,同样用 blkid 拿到这个逻辑卷的 UUID,写进 fstab。注意 LVM 逻辑卷的设备名在重启后一般稳定,但 fstab 里还是建议用 UUID 或完整的 /dev/data_vg/data_lv 路径,具体取决于你的管理习惯。既然用了 LVM,我更倾向于在 fstab 里写 /dev/data_vg/data_lv,因为只要 VG 名和 LV 名不变,这个路径就是确定的,而且一眼能看出是逻辑卷。
5.4 常用查看命令
pvs:看物理卷vgs:看卷组总量和剩余空间lvs:看逻辑卷大小和路径lvdisplay:看单个逻辑卷的详细信息
生产环境里我基本靠这三个简化命令快速了解全貌,比记住一堆长参数高效得多。
6. 扩容与缩容实战:LVM 一生中最常用的操作
逻辑卷创建出来必须会扩容,否则 LVM 的价值少了一半。
6.1 扩容:先扩 LV,再扩文件系统
容量的增加分两步走。第一步扩展逻辑卷:
bash复制lvextend -L +10G /dev/data_vg/data_lv
这里 +10G 表示在原有基础上增加 10GB。不加 + 就是直接扩展到某个固定大小:
bash复制lvextend -L 300G /dev/data_vg/data_lv
第二步是扩展文件系统。文件系统类型不同,命令不同。
ext4 用:
bash复制resize2fs /dev/data_vg/data_lv
xfs 用:
bash复制xfs_growfs /data
注意 xfs_growfs 参数是挂载点,不是设备路径。xfs 在线扩容是强项,文件系统直接在线扩大,不用卸载。ext4 也支持在线扩容,在绝大多数内核版本上都没问题。
扩容后检查:
bash复制df -h /data
lvs
6.2 卷组空间不够怎么办
如果 vgs 显示剩余空间不足,说明当初建的 VG 不够大。这时加一块新盘:
bash复制pvcreate /dev/sdd
vgextend data_vg /dev/sdd
然后重新执行 lvextend。整个过程不需要重启,服务不需要停。这也是 LVM 在生产环境里不可替代的原因之一:存储的整个生命周期都在线完成。
6.3 缩容一定要谨慎
缩容和扩容完全不对等。xfs 文件系统不支持缩减,这是死规矩。ext4 可以缩,但必须离线,而且缩容顺序和扩容相反:先缩文件系统,再缩逻辑卷。
顺序不能反,否则文件系统结构会被破坏。举个例子:
bash复制umount /data
e2fsck -f /dev/data_vg/data_lv
resize2fs /dev/data_vg/data_lv 200G
lvreduce -L 200G /dev/data_vg/data_lv
mount /data
e2fsck -f 强制检查,确保文件系统干净。resize2fs 先缩小到 200G,lvreduce 再缩逻辑卷。任何一步跳过,都可能丢数据。生产环境我一般不建议做缩容,性价比太低,风险高,宁可新起一个 LV 再迁移数据,也别在业务盘上缩。
6.4 匹配文件系统大小与 LV 大小
很多坑源于"LV 大了,文件系统没大"。比如你用 lvextend 扩了 LV,但忘了跑 xfs_growfs,df -h 看到的还是原来的容量。这个不是 bug,而是 LVM 和文件系统各自维护自己的大小。所以扩容后一定要确认两个层面的空间都到位。
7. 快照、PV 迁移与故障盘替换:进阶操作要谨慎
LVM 不止能扩容,还能做很多事情。这里说几个我实际用过的场景。
7.1 LVM 快照:备份前的一致性神器
LVM 快照可以在不停止业务的情况下,给逻辑卷创建一个一致性的镜像点。快照不是全量复制,它是 Copy-on-Write 机制,初始创建时几乎不占空间,但后续原始数据有变化时,会把旧数据保存到快照中。
创建快照:
bash复制lvcreate -L 10G -s -n data_lv_snap /dev/data_vg/data_lv
-s 表示 snapshot,-L 10G 是为快照预留的空间。快照空间大小取决于快照存活期间数据变化量,如果数据变化巨大,预留空间不够,快照就会损坏。所以快照别留太久,用完就删:
bash复制lvremove /dev/data_vg/data_lv_snap
我在生产环境里常用快照做备份前的"静默点",然后对快照设备进行备份,这样业务盘不会因为备份的 IO 负载受影响,数据一致性也有保障。
7.2 PV 迁移:不用拔盘也能换盘
当一块磁盘出现 IO 抖动或告警,需要更换时,可以先把它上面的数据迁移到同一 VG 的其他 PV 上:
bash复制pvmove /dev/sdb
这个命令把 /dev/sdb 上所有 PE 移动到 VG 中其他空闲 PV 上。如果 VG 没有其他空间,先 vgextend 加一块新盘再执行迁移。迁移期间服务不用停,但 IO 压力会比较大,建议在业务低峰期操作。迁移完成后:
bash复制vgreduce data_vg /dev/sdb
pvremove /dev/sdb
再把物理盘拔出更换。整个过程比传统"停服-拷数据-换盘-恢复"优雅得多。
7.3 实现根分区 LVM 注意激活时序
如果你把根目录 / 也放在 LVM 上,比如用 LVM 管理整个系统盘,需要注意 initramfs 阶段是否能识别卷组。现在主流发行版在安装时选择 LVM,mkinitcpio/dracut 都会自动把 LVM 支持加进去。但如果你手工改了 VG、LV 结构,或者把系统盘迁移到新机器,启动时可能出现找不到根分区的情况。这时要么重建 initramfs,要么在启动界面进 rescue 模式激活 VG:
bash复制vgchange -ay
这个命令激活所有 VG,然后重新扫描引导入口。
7.4 快照用于恢复误删数据
快照还有一个实用场景:升级软件或改配置前拍一个快照,出问题后直接回滚。操作上和创建快照一样,恢复时直接把逻辑卷从快照合并:
bash复制lvconvert --merge /dev/data_vg/data_lv_snap
合并需要目标 LV 不在使用中,生产环境要提前规划停机窗口。我没有把它当常规备份方案,但作为临时保险,确实好用。
8. 实操笔记:文档里没写清的坑
最后这部分,把我这些年踩过的坑集中说一下,每一条都是真金白银换来的。
第一,fstab 里写错 UUID 的代价。 之前有人改 fstab 时手动多打了一个字符,重启后系统起不来,报 Failed to mount。最后只能进单用户模式把 fstab 改回来。避免方式就是上面说的,改完先 mount -a,同时配置里使用 blkid 输出的完整 UUID,绝不手敲。
第二,xfs 缩容没人提醒你。 我见过有人对 xfs 执行 resize2fs,命令直接报错不支持,他才意识到选错了文件系统。如果需求明确包含缩容,建文件系统时就选 ext4。xfs 适合容量只增不减的日志、归档、数据库文件场景。
第三,LVM 的 PE 对齐和优化。 如果底层是 SSD,创建 PV 前建议参考厂商文档,确认磁盘分区对齐到 1MB 或更高。不对齐会影响 SSD 性能和寿命,这在 LVM 场景里容易被忽略。用 fdisk 或 parted 创建分区时,默认对齐一般没问题,但手工指定扇区时就要小心。
第四,组名和逻辑卷名别乱改。 有些人在还跑着业务时把 VG 重命名了,结果系统启动找不到原来的设备路径,直接掉进 emergency mode。LVM 设备路径包含 VG 名和 LV 名,改名就是改路径,必须先更新 fstab 和引导配置。
第五,Docker、NAS 挂载等场景里,LVM 依然适用。 Docker 数据卷可以放在 LVM 逻辑卷上,日志目录、容器数据目录容量紧张时,直接对 LV 做扩容,然后 xfs_growfs 让文件系统跟上。NAS 挂载走的是网络文件系统,思路不一样,但本地存储层用 LVM 打底,总体管理会轻松很多。开发板调试时,把 ubuntu 系统的 rootfs 挂载到板子上,也可以先用 LVM 划分空间,这样后面调试时扩容会方便很多。
第六,养成定期 vgs 的习惯。 我就靠这个命令发现过好几次卷组空间只剩几个 GB 的紧急情况。提前扩容,比等到磁盘写满再救急要从容太多。写满的后果不只是业务无法写入,还可能导致系统日志、数据库产生连锁故障,恢复起来不是简单扩容就完事的。
磁盘管理这件事,说到底就是一个思路:看清楚设备的物理层次,选对文件系统,再用 LVM 把容量和业务解耦。再稳定的技术也抵不过混乱的规划,遇到问题冷静下来用 lsblk、blkid、pvs、vgs、lvs 一步步看,多数问题都藏不住。我到现在也保留着一个习惯,所有新装的服务器都会第一时间把磁盘规划写成文档,把 UUID、VG、LV 的对应关系记录清楚,半年后有人问起,直接翻文档就能找到答案。
