面对一块新磁盘时,最危险的误解是把 /dev/sdb 当成一个已经可以存文件的“盘符”。它可能只是整盘设备,里面也许有分区表;某个分区上也许有文件系统;文件系统还要接入当前目录树,应用才会通过普通路径访问它。每一层都能独立存在,也有自己的标识和工具。
这篇内容从只读观察开始,再进入分区、格式化、挂载与持久配置。所有可能覆盖数据的示例都使用一次性容器中的稀疏镜像;命令输出来自实际运行,实验结束后已删除镜像和容器。真正操作存储设备时,请把“确认目标、保留备份、解除使用、写后复核”看成一个不可拆开的流程。

我们平时打开的是 /srv/data/report.csv 这样的路径,不是扇区。一次普通读取会经过系统调用、虚拟文件系统 VFS、具体文件系统驱动、块层和设备驱动,最后才抵达存储介质。VFS 提供统一的文件与目录接口,所以 ls、cp 不必知道下层是 ext4、XFS,还是网络文件系统。
从下往上看,一条常见路径是:
/dev/sda、/dev/nvme0n1。/srv/data。/srv/data/report.csv 读写。分区不是文件系统,文件系统也不是挂载点。/dev/sda2 可以存在但没有格式;ext4 签名可以存在但尚未挂载;同一个挂载点还可能临时被另一个文件系统覆盖。排错时如果跳过中间层,很容易拿着正确命令操作错误对象。
常见名称能提示接口形态,却不能单凭名字确认物理身份:
sdX 的字母通常反映驱动发现顺序。增删控制器、改变启动时序或插入移动盘后,原来的 /dev/sdb 可能变成 /dev/sdc。这就是为什么持续挂载配置更适合使用 UUID=、LABEL=、PARTUUID=,或经过评估的 /dev/disk/by-id/ 链接。
这里还要分清四个名字:

存储排错最有效的习惯,是让三个命令回答三个不同问题。
lsblk 关注块设备拓扑:谁是整盘、谁是分区、谁由谁映射、尺寸多大、当前显示哪些挂载点。交互查看可以使用:
lsblk -o NAME,PATH,TYPE,SIZE,FSTYPE,FSVER,LABEL,UUID,PARTUUID,MOUNTPOINTS脚本不要依赖默认列,因为 util-linux 可能调整默认输出。需要机器读取时,显式指定列并配合 --json。刚插入设备后,如果 udev 尚未完成属性填充,可以先等待事件稳定,再读取完整属性。
blkid 关注内容签名。它会探测某个设备或镜像中是否存在 ext4、XFS、swap 等签名,以及 UUID、LABEL 等标签:
sudo blkid -p /dev/sdb1低层探测出现多个冲突签名时,不应猜一个继续挂载。先用只读工具核实历史用途和备份,再决定是否清除旧签名。wipefs 的名字虽然像清理工具,但不带写选项查看时也能列签名;真正擦除仍是破坏性动作。
findmnt 关注当前挂载关系:某个路径属于哪个来源、类型和选项。比起在很长的 mount 输出里搜索,它能明确按 target 或 source 查询:
findmnt --target /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --source UUID=目标UUID -o TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --submounts /srv/data一次性容器里,lsblk 能看到 vda 与 vda1 的父子关系,而 findmnt -T /tmp/welearn-ch15 返回的是 overlay 根挂载。这说明块设备视图与进程所处的挂载命名空间不是同一张表。

分区表只描述磁盘上哪些扇区属于哪些分区,以及分区类型、名称等元数据。它不负责创建 ext4,也不负责把内容接到目录树。正因为分区工具直接改整盘的边界记录,选错设备往往比命令写错一个选项更致命。
任何修改前都按以下顺序确认:
lsblk -o NAME,PATH,TYPE,SIZE,MODEL,SERIAL,WWN,FSTYPE,UUID,MOUNTPOINTS
findmnt --source /dev/目标设备
findmnt --submounts /预计挂载点
sudo blkid -p /dev/目标设备
sudo fdisk -l /dev/目标整盘输出要与变更单中的容量、型号、序列号、现有分区和用途一致。确认所有相关文件系统已卸载、没有活跃 swap、没有 LVM/RAID/加密映射或虚拟机占用,并且备份能够在另一处读取。只说“盘里应该没数据”不是确认。
MBR 与 GPT 的主要差别不该只背成“旧和新”:

分区工具可以操作普通镜像文件。隔离实验创建了 128 MiB 稀疏文件,并用 sfdisk 写入 GPT:
LAB=/tmp/welearn-ch15
mkdir -p "$LAB"
truncate -s 128M "$LAB/gpt.img"
printf 'size=65536, type=L, name="data"\ntype=S, name="swap"\n' |
sfdisk --label gpt "$LAB/gpt.img"
sfdisk --dump "$LAB/gpt.img"
fdisk -l "$LAB/gpt.img"实际得到的关键部分是:
Disk /tmp/welearn-ch15/gpt.img: 128 MiB, 134217728 bytes, 262144 sectors
Sector size (logical/physical): 512 bytes / 512 bytes
Device Start End Sectors Size Type
/tmp/welearn-ch15/gpt.img1 2048 67583 65536 32M Linux filesystem
/tmp/welearn-ch15/gpt.img2 67584 260095 192512 94M Linux swap第一分区从第 2048 个 512 字节扇区开始,即偏移 1 MiB。第一条记录大小为 65536 个扇区,也就是 32 MiB。第二条记录只标记为 Linux swap;它还没有 swap 签名,更没有进入内核换页池。
实验结束执行 rm -rf /tmp/welearn-ch15,test ! -e /tmp/welearn-ch15 返回成功,随后 --rm 删除容器。这种练习的价值不只是“不会误伤”:镜像可以被复制、校验和比较,读者能反复观察分区表变化,而无需把一次不可逆操作当作教学过程。
mkfs.ext4 /dev/目标分区 看似只有一行,实际会写入超级块、块组描述符、inode 与块位图、inode 表、日志等结构。它不是“给现有文件补一个类型”,而是在目标范围内建立新的文件系统布局;旧签名和旧元数据可能因此不可用。
安全流程应是:再次确认目标未挂载且允许清空,查看现有签名,选定文件系统,再执行明确的类型工具。例如:
sudo blkid -p /dev/sdb1
sudo mkfs.ext4 -L DATA /dev/sdb1
sudo blkid -p /dev/sdb1小型隔离镜像的实际创建输出包含:
Creating filesystem with 98304 1k blocks and 24576 inodes
Filesystem UUID: 972d8da6-f46b-41f2-85aa-11bae68536ff
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729
Creating journal (4096 blocks): done这次镜像只有 96 MiB,所以工具按小型用途选择 1 KiB 块;不能把它当作所有 ext4 的固定块大小。默认参数会结合版本、配置和预期用途变化。生产环境只有在理解工作负载、恢复工具和兼容性之后,才应覆盖块大小、inode 密度、特性集或保留块比例。
blkid -p 随后读到 LABEL、UUID、块大小和 TYPE。再用 tune2fs -L CH15_LAB 修改卷标,UUID 保持不变,说明二者是独立字段。克隆完整文件系统会连 UUID 一起复制,因此接入克隆盘后要主动检查重复标识,不能因为 UUID 名字里有“唯一”就省略复核。

loop 设备把普通文件呈现为块设备。它很适合练习分区扫描、文件系统创建和挂载,也常用于磁盘镜像、只读介质与某些包格式。最小生命周期是“创建后备文件 → 关联 loop → 操作 → 卸载 → 解除关联 → 删除文件”。
LAB=/tmp/welearn-ch15
truncate -s 512M "$LAB/disk.img"
LOOP=$(sudo losetup --find --show --partscan "$LAB/disk.img")
printf '%s\n' "$LOOP"
: "只操作 $LOOP 及其分区,完成后执行清理"
sudo umount /mnt/lab
sudo losetup --detach "$LOOP"
rm -f "$LAB/disk.img"--find --show 返回实际分配的 loop 名,脚本应保存这个返回值,不能假定永远是 /dev/loop0。--partscan 请求内核扫描镜像中的分区表。并行流程还要防止同一后备文件被建立多个重叠映射;那会让两个写入者绕过彼此的缓存与一致性假设。
稀疏文件还有一个容易误判的地方。隔离实验中:
$ truncate -s 96M ext4.img
$ du -h ext4.img
0 ext4.img
$ du -h --apparent-size ext4.img
96M ext4.img逻辑长度是 96 MiB,但未写区域不占等量物理块。把稀疏镜像复制到不保留稀疏属性的目标、压缩或写入后,真实占用可能增长。容量规划要同时看 apparent size 和 allocated blocks。
为了保持最低权限,前述 ext4 实验直接对普通镜像运行 mkfs.ext4、blkid -p、dumpe2fs、e2fsck -fn 和 debugfs,没有授予容器挂载能力,也没有建立 loop。这同样验证了磁盘格式,而且清理面更小。
手动挂载需要回答四件事:来源是什么、内容类型是什么、接到哪个目录、使用哪些选项。典型形式是:
sudo mkdir -p /mnt/lab
sudo mount -t ext4 -o ro,nosuid,nodev /dev/loop0 /mnt/lab
findmnt --target /mnt/lab -o TARGET,SOURCE,FSTYPE,OPTIONS挂载点必须是目录。若目录原来已有文件,挂载后这些文件会被新文件系统遮住,但没有被删除;卸载后又会出现。这种覆盖是常见的“文件突然不见了”原因。先用 findmnt -T 路径 判断路径属于哪个文件系统,再决定去哪一层找数据。
挂载选项是一组策略,不是万能安全开关:
ro 以只读方式挂载,适合初次检查未知介质或恢复副本。rw 允许文件系统驱动执行写入;它不代表每个文件都能绕过 Unix 权限。nodev 不解释该挂载中的设备特殊文件,适合不受信任的数据介质。nosuid 禁止该挂载上的 set-user-ID/set-group-ID 位提升身份。noexec 阻止从该挂载直接执行二进制映像,但脚本仍可能被显式传给解释器读取,因此不能当作代码沙盒。sync 挂载选项会改变 I/O 行为,不等于偶尔执行一次 sync;不要为了“更安全”在不了解性能和一致性语义时全局添加。不同文件系统支持的选项不同。FAT/exFAT 不保存与 ext4 相同的 Unix 所有者和模式位,通常用 uid=、gid=、umask= 或相关选项投影权限。把 ext4 的权限经验原样套过去,会得到看似奇怪但其实符合实现的结果。

umount /mnt/data 的目标是从挂载命名空间解除文件系统。内核拒绝忙碌的挂载,通常是因为仍有引用:进程打开了文件、工作目录在里面、存在子挂载、挂载内的 swap 文件仍活跃,或者服务正在执行 I/O。
一个稳健的诊断顺序是:
findmnt --target /mnt/data -o TARGET,SOURCE,FSTYPE,OPTIONS
findmnt --submounts /mnt/data
fuser -vm /mnt/data
lsof +f -- /mnt/data如果当前 Shell 位于挂载内,先 cd /。对数据库和日志服务,应让应用正常停机或关闭文件,而不是直接杀进程。存在子挂载时从最深层开始卸载。若挂载内有 swap 文件,先用 swapon --show 确认,再评估剩余内存与其他 swap 是否足以承接活跃页,最后才考虑 swapoff。
sync 请求把缓存写回持久存储,但它不能替应用提交事务,也不会解除打开文件。正常 umount 会处理文件系统同步并报告结果。对于移动介质,安全信号是 umount 成功且 findmnt 不再显示挂载,而不是“复制窗口已经关了”。
umount -l 会先从目录树分离,已有引用仍可继续存在;它适合特定恢复场景,却可能把资源留在后台。-f 主要用于某些失联网络文件系统,也不保证解决本地占用。把两者当作日常“强制拔盘”按钮,会隐藏根因。
/etc/fstab 不是“开机执行几条 mount 命令”的随手清单。它描述来源、目录、类型和策略,mount、fsck、swapon 以及 systemd 生成器都会读取它。一个常见本地数据卷条目是:
UUID=7d0a6d2e-1111-4444-8888-123456789abc /srv/data ext4 defaults,nosuid,nodev 0 2六个字段从左到右是:
字段先按空白拆分,所以路径或 LABEL 中的空格不能靠引号解决,应转义为 \040;制表符用 \011。defaults 不是“最安全选项集”,它代表常规默认行为,并会随内核和文件系统而有细节差异。
可移动介质常用 noauto 避免 mount -a 和启动流程主动挂载;非关键设备可评估 nofail,防止缺席时阻断启动目标,但这也意味着依赖该目录的应用必须自己验证挂载成功。网络块设备或网络文件系统常需 _netdev 与合理超时,避免在网络可用前按本地盘处理。
修改前备份文件,写后先做静态核对:
sudo cp -a /etc/fstab /etc/fstab.before-storage-change
findmnt --verify --verbose
sudo systemctl daemon-reload
sudo mount -a
findmnt --target /srv/data -o TARGET,SOURCE,FSTYPE,OPTIONSmount -a 不是无风险语法检查,它会尝试挂载未挂载且没有 noauto 的条目,所以要在可恢复会话中执行,并先确认每一行的来源。隔离实验只让 findmnt --fstab --tab-file 解析一个临时表,没有真正挂载;输出正确拆出了 source、target、type 和 options。

在 systemd 环境中,systemd-fstab-generator 会在启动早期和管理器 reload 时,把 fstab 条目转换成 .mount 与 .swap 单元。挂载点决定单元名,例如 /srv/data 对应 srv-data.mount;路径中的连字符还要按 unit 名规则转义。
挂载单元会自动获得一部分依赖:下层设备必须出现,父目录所在挂载要先准备,本地文件系统通常进入 local-fs.target,网络文件系统进入远程挂载目标。nofail、_netdev、x-systemd.automount、x-systemd.device-timeout= 等选项会改变等待、依赖或按需触发方式。
这解释了几个常见现象:
nofail/超时策略,启动可能等待设备。x-systemd.automount 创建自动挂载单元,第一次访问路径时才触发真正挂载;这不是“永远已挂载”。桌面移动盘通常由 udev 事件、udisks 和会话策略协作挂载。插入设备后可以观察:
udevadm monitor --kernel --udev --property
lsblk -o NAME,TYPE,SIZE,TRAN,LABEL,UUID,MOUNTPOINTS
journalctl -k --since -2min设备节点出现、文件系统被识别、桌面自动挂载是三个阶段。复制完成后仍要正常卸载。光学介质多为只读 iso9660,设备常见 /dev/sr0;USB 存储虽常显示为 /dev/sdX,也不能据此把它当作固定内置盘。
df 读取文件系统整体的块与 inode 统计,回答“这个文件系统还有多少可分配资源”。传入路径可以避免在众多伪文件系统中找错行:
df -hT /var/log
df -i /var/logdu 沿目录树累计文件占用,回答“从这个目录还能通过名称找到哪些数据”:
du -xhd1 /var | sort -h
du -xhd1 /var/log | sort -h-x 限制在一个文件系统内,防止跨进子挂载。du 默认看已分配块,--apparent-size 看逻辑长度;稀疏文件会让两者差很多。
df 高、du 低并不自动表示统计错误。常见原因包括:
lsof +L1 查找。字节空间并非唯一资源。大量零碎小文件可能先耗尽 inode,此时 df -h 还有空间,新文件仍会报 No space left on device。要同时看 df -i,再找产生大量小文件的目录。

文件系统依靠超级块、位图、inode、目录项和日志彼此一致。突然掉电、介质错误、驱动问题或错误的原始写入可能让这些结构出现矛盾。日志能缩小崩溃后的恢复范围,却不是备份,也不能修复硬件继续返回错误数据的问题。
对 ext4 的稳健处理顺序是:停止写入,记录错误,确认来源设备和下层健康,卸载文件系统,先只读检查,再决定修复。隔离镜像使用:
e2fsck -fn /tmp/welearn-ch15/ext4.img实际输出依次检查 inode/块/尺寸、目录结构、目录连通性、引用计数和组摘要,最后报告 clean。-n 以只读方式打开并对修复问题回答 no;-f 即使状态看起来干净也执行完整检查。
不要对正常读写挂载的文件系统运行 fsck。内核可能同时修改元数据,检查工具依据的快照会不断变化,所谓“修复”反而制造冲突。根文件系统的修复通常需要从恢复环境启动,或在真正只读且满足工具要求的特殊维护模式完成。
如果怀疑硬件故障,优先制作只读镜像或在副本上恢复。debugfs 默认只读,能检查 ext 系列内部对象;写模式非常强,不能把它当作普通文件管理器。备用超级块也不是随意试错的邀请:必须匹配文件系统创建参数,错误写入可能扩大损坏。
修复命令会改变证据和元数据。先保存日志、确认下层设备、准备可回退副本,再决定是否写入;“让 fsck 对所有问题自动回答 yes”不等于可靠恢复策略。

内存压力出现时,内核可以把不活跃的内存页移到 swap,为活跃工作集腾出 RAM。swap 可以是分区,也可以是满足约束的普通文件;它不提供目录、文件名或 mount 路径。
创建与激活是两个阶段:
sudo mkswap -L DATA_SWAP /dev/sdb2
sudo swapon /dev/sdb2
swapon --show --output NAME,TYPE,SIZE,USED,PRIOmkswap 会写 swap 签名,并让旧文件系统签名不可正常使用;选错目标同样会丢数据。swapon 才把区域加入内核换页池。隔离实验对 32 MiB 文件执行 mkswap,blkid -p 识别到 TYPE="swap",但 swapon --show 中没有该文件,因为没有执行激活。
swap 文件必须没有不受支持的空洞,并受底层文件系统限制。写时复制文件系统、快照、压缩和预分配的组合可能需要专门流程;不要只因 fallocate 返回成功就断定可用。文件权限通常设为 600,持久配置可写:
/swapfile none swap defaults,pri=10 0 0停用用 swapoff。如果区域里已有活跃页,内核要把它们迁回 RAM 或其他 swap;可用容量不足时会失败,贸然停用还可能把系统推向 OOM。先查看内存、所有 swap 的容量与使用量,再规划迁移。
直接分区把逻辑范围固定在一块盘上。LVM 在其上增加可管理的映射层:一个或多个 PV 组成 VG 空间池,再从 VG 分配 LV。LV 是新的块设备,可在其上创建 ext4、XFS 或 swap:
/dev/nvme0n1p3 ─┐
├─ PV → VG=data_vg → LV=archive → ext4 → /archive
/dev/sdb1 ──────┘pvs、vgs、lvs 分别查看三层;lsblk 能把部分父子关系串起来,/dev/mapper/ 提供可读的映射名。扩展 LV 只扩大块设备,文件系统还要按类型扩展。缩容更危险:不是所有文件系统都支持缩小,顺序错误会把文件系统尾部截断。本节只要求识别层次和故障边界,不提供生产缩容、迁移或 PV 移除步骤。
软件 RAID 解决跨设备的冗余、性能或容量组合问题,LVM 解决空间池与逻辑卷管理问题,两者可以叠加,但语义不同。RAID1 也无法防止误删除、勒索软件、文件系统逻辑损坏或控制器把坏数据同步到所有副本,所以 RAID 不是备份。
加密层同样常由 Device Mapper 提供。解锁产生 /dev/mapper/... 块设备,文件系统再位于其上。排错时要问清是物理设备故障、阵列降级、PV 缺失、映射未激活、文件系统损坏,还是单纯没有挂载;“/data 不见了”可能发生在任何一层。
挂载成功后出现 Permission denied,不一定是 mount 失败。对 ext4、XFS 等原生 Unix 文件系统,所有者和模式位存储在文件系统内;把一个旧数据卷挂到新系统,数字 UID/GID 可能对应不同账户。先用 stat、namei -l 和身份数据库核对,不要直接递归 chmod 777。
FAT/exFAT 没有同样的每文件 Unix 所有权语义,挂载时的 uid=、gid=、umask=、fmask=、dmask= 会影响整个视图。CIFS、NFS 又有各自的身份与权限映射。看到权限问题时,要先确认文件系统类型,再解释 ls -l。
安全选项需要组合使用:不受信任移动盘可先只读,并评估 nodev,nosuid,noexec;服务数据盘则要按应用需求决定执行、setuid 与设备文件。它们减少攻击面,但不能检查文件内容、阻止解释器读取脚本,或代替进程隔离。
一致性策略也要包含权限边界。普通用户若能格式化任意块设备、修改 fstab 或挂载任意来源,就能越过许多目录级权限。只授予完成任务所需的最小能力,把可移动介质的授权交给明确策略,并保留操作日志。
存储故障不该从“多试几个 mount 参数”开始。先按症状定位层次:
例如,lsblk 看见 /dev/sdb1,blkid 识别 ext4,findmnt 却没有挂载,而手动 mount 返回超级块错误。此时问题已经从设备发现和分区层缩小到文件系统或下层 I/O。合理动作是保存错误和内核日志、保持只读、检查设备健康、在副本上运行只读一致性检查;重新分区或 mkfs 会直接抹掉最有价值的恢复线索。
如果 fstab 条目偶发失败,还要核对稳定标识是否重复、设备出现时间、systemd 依赖和超时。若 /srv/data 未挂载但服务仍能写入,同名普通目录可能悄悄接收数据,最终造成根文件系统被写满。关键服务可以在启动前用 findmnt --mountpoint /srv/data 或等价健康检查确认挂载确实存在。
把全章压缩成实际工作流,可以分成五个关口。
关口一:只读识别。 用显式列的 lsblk 确认拓扑、容量、型号和标识;用 blkid -p 确认签名;用 findmnt 确认所有挂载与子挂载。记录输出,不凭印象选设备。
关口二:风险隔离。 确认备份可读,停止服务,解除挂载、swap、LVM/RAID/加密与虚拟机占用。练习先用容器和镜像;生产变更保留控制台或恢复环境。
关口三:一次只改一层。 先改分区表并重新读取、复核边界;再创建文件系统并复核 UUID/LABEL;最后建立临时挂载并检查来源与选项。不要把分区、格式化、挂载塞进一个看不见中间状态的长管道。
关口四:持久配置预演。 备份 fstab,做静态解析,reload systemd,在可恢复会话运行 mount -a,再用 findmnt 读回实际状态。验证缺盘、只读、超时和服务依赖的失败路径。
关口五:清理与证据。 正常卸载,确认挂载消失,解除 loop 或映射,删除临时镜像,检查没有活跃 swap 和容器残留。保存命令、关键输出、退出状态和回退动作,下一次才能复现。
可以用下面的隔离练习检验自己:创建稀疏镜像,在其中写 GPT;对另一个镜像创建 ext4、设置 LABEL、读取 UUID、运行 e2fsck -fn;让 findmnt 解析一份临时 fstab;创建 swap 签名但不激活;最后删除整个实验目录并让容器 --rm 退出。每一步都要写出“当前改变的是哪一层、下一条只读命令怎样证明它”。