教程

在 Linux 中挂载磁盘:lsblk、分区、mkfs、mount 与 fstab

更新于: · Skillaria.Top

在 Linux 中挂载磁盘,就是把分区的文件系统接入目录树中的某个目录,例如 /data。先用 lsblk 找到新磁盘,用 fdisk 或 parted 分区,用 mkfs.ext4 格式化,再用 mount /dev/sdb1 /data 挂载。要让分区在重启后自动挂载,需要在 /etc/fstab 中添加使用其 UUID 的一行,并用 mount -a 检查。

Linux 中没有盘符:所有存储设备都被挂入以 / 为根的同一棵目录树。挂载磁盘就是把分区的文件系统“挂接”到一个空目录上,这个目录称为挂载点。新磁盘的流程总是相同的:找到设备(lsblk),分区(fdisk 或 parted),创建文件系统(mkfs),挂载(mount),最后写入 /etc/fstab 固定下来。下面逐步讲解,并介绍如何用 df 和 du 查明空间去了哪里。

Linux 中磁盘和分区的结构

内核把每块磁盘表示为 /dev 中的一个设备文件。名称取决于连接方式:

名称说明分区
/dev/sda、/dev/sdbSATA/SAS/USB 磁盘,许多虚拟磁盘也使用此命名/dev/sda1、/dev/sda2
/dev/vdaKVM 虚拟机中的 virtio 磁盘/dev/vda1
/dev/nvme0n1NVMe SSD/dev/nvme0n1p1
/dev/mapper/...LVM 逻辑卷、加密卷—

磁盘被划分为分区,分区上创建文件系统(ext4、xfs、btrfs),然后挂载到某个目录。分区未挂载时,其中的文件不可访问,即使磁盘已经物理连接。

查看磁盘:lsblk 和 blkid

处理磁盘时,第一个命令是 lsblk。它显示设备树、大小以及挂载点:

$ lsblk
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sda      8:0    0   40G  0 disk
├─sda1   8:1    0    1G  0 part /boot
└─sda2   8:2    0   39G  0 part /
sdb      8:16   0  100G  0 disk

这里可以看到 sdb 是一块 100 GB 的新磁盘,没有分区,也没有挂载点。其他常用选项:

  • lsblk -f — 每个分区的文件系统类型、标签和 UUID。
  • lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,MODEL — 只显示需要的列。
  • sudo blkid — 所有分区的 UUID 和文件系统类型。
  • sudo fdisk -l — 所有磁盘的分区表,包括扇区信息。

如果是在虚拟机中热添加的磁盘而 lsblk 没有显示,可以让内核重新扫描总线:echo "- - -" | sudo tee /sys/class/scsi_host/host*/scan。

分区:fdisk 和 parted

分区之前,请再次确认选中的设备是正确的:写入分区表会销毁系统盘上的数据。根据 lsblk 输出中的大小以及没有挂载点来判断。

GPT 还是 MBR

对于新磁盘应使用 GPT:它支持超过 2 TB 的磁盘,最多 128 个分区。MBR(dos)只在使用 BIOS 启动、且引导程序要求时才需要。

使用 fdisk 分区

现代的 fdisk 同时支持 GPT 和 MBR。操作在交互模式下进行:

$ sudo fdisk /dev/sdb
Command (m for help): g        # 创建空的 GPT 分区表
Command (m for help): n        # 新建分区
Partition number (1-128, default 1): Enter
First sector: Enter
Last sector, +/-sectors or +/-size{K,M,G,T,P}: Enter   # 整块磁盘
Command (m for help): w        # 写入更改并退出

在按下 w 之前,不会向磁盘写入任何内容,因此输入 q 可以不作任何更改直接退出。

用 parted 一行完成分区

在脚本中,parted 更方便,它无需交互:

$ sudo parted -s /dev/sdb mklabel gpt
$ sudo parted -s /dev/sdb mkpart primary ext4 0% 100%
$ lsblk /dev/sdb
NAME   MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
sdb      8:16   0  100G  0 disk
└─sdb1   8:17   0  100G  0 part

用百分比指定边界可以保证分区对齐。如果新分区没有出现,执行 sudo partprobe /dev/sdb,让内核重新读取分区表。

创建文件系统:mkfs

分区只是一段数据块范围。要存放文件,必须在其上创建文件系统:

$ sudo mkfs.ext4 -L data /dev/sdb1
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 26214144 4k blocks and 6553600 inodes
...
Writing superblocks and filesystem accounting information: done

参数 -L 设置卷标,以后便于识别分区。如何选择:

文件系统命令适用场景
ext4mkfs.ext4通用的默认选择,可以缩小
XFSmkfs.xfs大文件和大卷,RHEL 的标准;只能扩大
Btrfsmkfs.btrfs快照、压缩、子卷
vfat/exFATmkfs.vfat、mkfs.exfat与 Windows 和 macOS 交换数据的 U 盘

mkfs 会清除分区上的所有内容。对于空分区,命令不会要求确认,因此请再次核对设备名称。

用 mount 挂载磁盘

创建一个目录作为挂载点,然后把分区挂到该目录上:

$ sudo mkdir -p /data
$ sudo mount /dev/sdb1 /data
$ df -h /data
Filesystem      Size  Used Avail Use% Mounted on
/dev/sdb1        98G   24K   93G   1% /data

mount 会自动识别文件系统类型,也可以显式指定:mount -t xfs。如果 /data 中原本有文件,挂载后它们不会被删除,只是被新文件系统遮住,卸载后会重新出现。

挂载选项

选项通过 -o 传递,用逗号分隔:

  • ro / rw — 只读或读写。
  • noatime — 读取时不更新访问时间,减少不必要的写入。
  • noexec — 禁止从该分区运行程序(适用于 /tmp 和下载目录)。
  • nosuid、nodev — 忽略 SUID 位和设备文件。
  • remount — 不卸载即可修改选项:sudo mount -o remount,ro /data。

要查看挂载了什么以及使用了哪些选项,可以用 findmnt:findmnt /data 或 findmnt -t ext4。

挂载后的权限

新 ext4 的根目录属于 root,因此普通用户无法写入。挂载后把目录交给需要的用户:sudo chown alice:alice /data。对于 vfat 和 exFAT,没有 Unix 权限,所有者需要在挂载时通过 uid=、gid= 和 umask= 选项指定。

卸载磁盘:umount 与 target is busy 错误

卸载使用 umount(注意没有字母 n),参数可以是设备或目录:

$ sudo umount /data
umount: /data: target is busy.

这个错误表示有进程正在使用该文件系统上的文件,或者以它为当前目录——常见情况是你在终端中执行了 cd /data。查找占用者可以使用:

$ sudo lsof +f -- /data
$ sudo fuser -vm /data

结束该进程,或退出该目录,然后重试。最后的办法是 umount -l(lazy,延迟卸载):文件系统会立即从目录树中分离,待进程关闭文件后再真正释放。

开机自动挂载:/etc/fstab

mount 命令只在重启前有效。要让磁盘自动挂载,需要在 /etc/fstab 中添加一行。请使用 UUID 指定分区,而不是 /dev/sdb1 这样的名称:添加磁盘时设备名可能会互换,而 UUID 是固定的。

$ sudo blkid /dev/sdb1
/dev/sdb1: LABEL="data" UUID="3f1c9a2e-7b5d-4c1e-9a8f-2d6e4b0c1a77" TYPE="ext4" PARTUUID="..."

每行包含六个字段:

# <设备>                                  <挂载点>  <类型>  <选项>            <dump> <fsck>
UUID=3f1c9a2e-7b5d-4c1e-9a8f-2d6e4b0c1a77  /data    ext4   defaults,noatime  0      2
字段含义
设备UUID=...、LABEL=... 或路径
挂载点挂载到的目录(必须已存在)
类型ext4、xfs、swap、nfs 等
选项defaults 加上需要的选项,例如 noatime、nofail
dump通常为 0
fsck检查顺序:根分区为 1,其他为 2,0 表示不检查

重启前一定要检查 fstab

/etc/fstab 中的一个错误可能导致服务器启动时进入紧急模式;在没有控制台的云主机上,这会非常麻烦。修改之后立即执行:

$ sudo findmnt --verify
$ sudo systemctl daemon-reload
$ sudo mount -a
$ findmnt /data

mount -a 会挂载 fstab 中所有尚未挂载的条目,并立即显示错误。对于可移动或网络磁盘,添加 nofail 选项:如果设备不存在,启动仍会继续。在 systemd 中,fstab 的每一行都会转换为一个 .mount 单元,例如 data.mount,可以通过 systemctl status data.mount 查看其状态。

查看可用空间:df

df 显示已挂载文件系统的占用情况:

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2        39G   37G  1.1G  98% /
/dev/sda1       974M  180M  727M  20% /boot
/dev/sdb1        98G   24K   93G   1% /data
  • -h — 以易读的单位显示大小。
  • -T — 增加一列显示文件系统类型。
  • -i — 显示 inode 情况:如果创建了大量小文件,磁盘可能在仍有剩余 GB 的情况下“用完”。
  • -x tmpfs -x devtmpfs — 隐藏虚拟文件系统。

为什么 Size 不等于 Used + Avail:ext4 会为 root 保留约 5% 的空间,以便系统在磁盘写满时仍能工作。对于存放数据的分区,可以减少这部分保留:sudo tune2fs -m 1 /dev/sdb1。

空间去哪儿了:du

df 告诉你磁盘满了,但没有说明是什么占用了空间。这时可以用 du,它会汇总目录中文件的大小:

$ sudo du -sh /var/log
4.2G    /var/log
$ sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head
37G     /
21G     /var
9.8G    /home
3.1G    /usr
  • -s — 只显示目录的总计,-a — 显示每个文件。
  • --max-depth=1(或 -d 1)— 只显示一层;再对最大的目录逐层深入。
  • -x — 不跨越文件系统边界,否则 /data、/proc 和网络磁盘都会计入总和。
  • sort -rh — 按易读的大小排序,最大的在最上面。

要找单个大文件,用 find 更方便:sudo find / -xdev -type f -size +1G -exec ls -lh {} +。

df 显示磁盘已满,而 du 看不到原因

典型情况:删除了一个很大的日志,空间却没有释放。文件已从目录中删除,但某个进程(例如 Web 服务器)仍然打开着它,因此数据块没有被释放。查找这类文件:

$ sudo lsof +L1
COMMAND  PID USER   FD   TYPE DEVICE   SIZE/OFF NLINK  NODE NAME
nginx    812 www    5w   REG    8,2 8589934592     0 13054 /var/log/nginx/access.log (deleted)

重启该进程或让它重新打开日志文件,空间就会释放。今后清理正在使用的日志时,可以不删除文件而直接清空:sudo truncate -s 0 /var/log/nginx/access.log。另一个导致差异的原因是挂载点下面的文件:它们仍占用根分区的空间,但文件系统挂载在其上方时 du 看不到它们。

常见错误及解决方法

信息原因解决方法
mount point /data does not exist目录不存在sudo mkdir -p /data
wrong fs type, bad option, bad superblock分区上没有文件系统,类型不对,或缺少驱动检查 lsblk -f;对于 exFAT/NTFS 安装 exfatprogs、ntfs-3g
only root can do that没有 sudo 就执行挂载使用 sudo,或在 fstab 中添加 user 选项
target is busy目录正被进程占用使用 lsof/fuser 查找,并退出该目录
启动时进入紧急模式fstab 有错误,或磁盘不存在以 root 登录,修正 fstab,添加 nofail

分步示例:为数据准备一块新磁盘

  1. lsblk — 找到新磁盘,例如 /dev/sdb。
  2. sudo parted -s /dev/sdb mklabel gpt mkpart primary ext4 0% 100% — 分区。
  3. sudo mkfs.ext4 -L data /dev/sdb1 — 创建文件系统。
  4. sudo mkdir -p /data — 创建挂载点。
  5. sudo blkid /dev/sdb1 — 获取 UUID,并把对应行添加到 /etc/fstab。
  6. sudo mount -a && df -h /data — 挂载并检查。
  7. sudo chown 用户名: /data — 分配权限。

如果以后需要在不停止服务的情况下扩展空间,或者要合并多块磁盘,可以使用 LVM 而不是普通分区:磁盘成为物理卷,从中切出逻辑卷,之后用 lvextend -r 即可扩容。

总结

在 Linux 中挂载磁盘遵循 lsblk → 分区 → mkfs → mount → /etc/fstab 的流程。分区使用 UUID 指定,用 mount -a 在重启前检查 fstab,对于非必需的磁盘使用 nofail。空间不足时,df -h 会告诉你哪个分区已满,而 du -xh --max-depth=1 | sort -rh 和 lsof +L1 可以找出是什么占用了它。磁盘、分区、swap、LVM 和 RAID 的实际操作,我们在 Linux 课程中都有讲解。

常见问题

如何在 Linux 中挂载 U 盘?

用 lsblk 找到它(通常是 /dev/sdb1),创建一个目录,然后执行 sudo mount /dev/sdb1 /mnt/usb。在图形桌面环境中,U 盘通常会自动挂载到 /media/用户名 或 /run/media 下。

如何挂载 ISO 镜像?

使用 sudo mount -o loop,ro image.iso /mnt/iso:loop 选项把文件当作块设备挂载。卸载镜像使用普通的 umount。

如何通过 fstab 挂载网络共享目录?

对于 NFS,一行写作 server:/export /mnt/nfs nfs defaults,_netdev,nofail 0 0;对于 SMB,写作 //server/share /mnt/smb cifs credentials=/root/.smbcred,_netdev,nofail 0 0。_netdev 选项表示等待网络就绪。

UUID 和 PARTUUID 有什么区别?

UUID 属于文件系统,重新执行 mkfs 后会改变;PARTUUID 属于 GPT 分区表中的分区,重新格式化后保持不变。fstab 中通常使用 UUID。

如何检查文件系统是否有错误?

先卸载分区,然后对 ext4 运行 sudo fsck -f /dev/sdb1,对 XFS 运行 sudo xfs_repair /dev/sdb1。不能对已挂载并在写入的文件系统进行检查,否则可能损坏数据。

通过视频学习本主题

课程“Linux: с нуля до уверенного администрирования”结合实践详细讲解了这一主题。

前往课程