在 Linux 中挂载磁盘:lsblk、分区、mkfs、mount 与 fstab
在 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/sdb | SATA/SAS/USB 磁盘,许多虚拟磁盘也使用此命名 | /dev/sda1、/dev/sda2 |
/dev/vda | KVM 虚拟机中的 virtio 磁盘 | /dev/vda1 |
/dev/nvme0n1 | NVMe 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 设置卷标,以后便于识别分区。如何选择:
| 文件系统 | 命令 | 适用场景 |
|---|---|---|
| ext4 | mkfs.ext4 | 通用的默认选择,可以缩小 |
| XFS | mkfs.xfs | 大文件和大卷,RHEL 的标准;只能扩大 |
| Btrfs | mkfs.btrfs | 快照、压缩、子卷 |
| vfat/exFAT | mkfs.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 |
分步示例:为数据准备一块新磁盘
lsblk— 找到新磁盘,例如/dev/sdb。sudo parted -s /dev/sdb mklabel gpt mkpart primary ext4 0% 100%— 分区。sudo mkfs.ext4 -L data /dev/sdb1— 创建文件系统。sudo mkdir -p /data— 创建挂载点。sudo blkid /dev/sdb1— 获取 UUID,并把对应行添加到/etc/fstab。sudo mount -a && df -h /data— 挂载并检查。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。不能对已挂载并在写入的文件系统进行检查,否则可能损坏数据。