← cd ../posts

挂载与文件系统:ext4 / btrfs / xfs / tmpfs 怎么挑、mount 在干啥

2026-06-26

这是 Linux 系列的第 13 篇。上一篇拆开了"文件"这个抽象——这一篇往下一层:文件**所在的那块"盘"**到底是什么、怎么接到系统上。

0. 三个名词先分清

块设备(block device)          ┐
   /dev/sda、/dev/nvme0n1、     │ 硬件层(或虚拟硬件)
   /dev/loop0                  ┘
                                
文件系统(filesystem)           ┐  
   ext4 / btrfs / xfs / vfat    │ 把块设备格式化后才有的"目录树"格式
                                ┘
                                
挂载点(mount point)            ┐
   /、/home、/mnt/data          │ 文件系统接入目录树的位置
                                ┘

类比:"硬盘是空白本子(块设备),格式化像在本子上画好横线规则(文件系统),mount 是把这个本子接到图书馆的某个书架位置(挂载点)"。

ls /home 就是查看接在 /home 这个位置的本子。


1. 看一眼你机器现在挂了什么

$ mount | head -10
proc on /proc type proc (rw,nosuid,nodev,noexec,relatime)
sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime)
/dev/sda1 on / type ext4 (rw,relatime,errors=remount-ro)
tmpfs on /run type tmpfs (rw,nosuid,nodev,size=204800k,mode=755)
/dev/sda1 on /home type ext4 (rw,relatime,errors=remount-ro)
tmpfs on /tmp type tmpfs (rw,nosuid,nodev,size=2048M)
...

每行:<块设备> on <挂载点> type <fs 类型> (<选项>)

更易读的工具:

$ findmnt
TARGET               SOURCE     FSTYPE  OPTIONS
/                    /dev/sda1  ext4    rw,relatime,errors=remount-ro
├─/proc              proc       proc    rw,nosuid,nodev,noexec,relatime
├─/sys               sysfs      sysfs   rw,nosuid,nodev,noexec,relatime
├─/run               tmpfs      tmpfs   rw,nosuid,nodev,size=204800k
├─/dev/shm           tmpfs      tmpfs   rw,nosuid,nodev
├─/home              /dev/sda2  ext4    rw,relatime
└─/mnt/data          /dev/sdb1  xfs     rw,relatime

findmnt 用树形展示更直观,强烈推荐。

看磁盘使用

$ df -h                     # 按挂载点列空间
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda1        50G   28G   22G  56% /
/dev/sdb1       500G   89G  411G  18% /mnt/data
tmpfs           2.0G  120M  1.9G   6% /tmp

$ df -ih                    # 按 inode 列(上一篇讲过)
$ df -T                     # 也显示 fs 类型

看块设备

$ lsblk
NAME    SIZE  TYPE MOUNTPOINTS
sda      50G  disk
├─sda1   49G  part /
└─sda2    1G  part [SWAP]
sdb     500G  disk
└─sdb1  500G  part /mnt/data
nvme0n1 1.0T  disk
└─nvme0n1p1 1.0T part /var/lib/docker

lsblk 是看"机器上有多少盘、每盘怎么分区、挂在哪"的最好工具。没挂载的盘这里也能看到。


2. 主流文件系统怎么挑

FS 甜点 不适合
ext4 默认、最稳、跨发行版兼容 单文件超过 16TB;高并发数据库(可选别的)
xfs 大文件、高并发 I/O、生产服务器 不能在线缩小(只能扩)
btrfs 快照、子卷、压缩、checksum 历史上 RAID5/6 不稳;某些场景内存压力大
zfs 同上 + 更成熟、双向 dedup、ARC 缓存 内存吃得多("1GB RAM per 1TB data" 经验值)、license 复杂
tmpfs 全在 RAM,重启即清空 任何不能丢的数据
vfat / exFAT U 盘、跨 Win/Mac 兼容 不支持 Unix 权限、单文件最大 4GB(vfat)

给一台普通服务器选

  • 系统盘:ext4(默认就好,不折腾)
  • 数据盘:xfs(如果数据量大)或 ext4(如果省事)
  • 想要快照 / 备份:btrfszfs
  • 容器跑临时数据:直接用 host 的 ext4,别折腾

3. mount 命令:手动接一块盘

假设你刚 attach 了一块新的 EBS / 阿里云数据盘,系统里识别为 /dev/vdb

# 1. 看一眼是不是真的没格式化过
$ sudo lsblk -f /dev/vdb
NAME FSTYPE LABEL UUID SIZE MOUNTPOINTS
vdb               500G                     ← FSTYPE 为空 = 没格式化

# 2. 格式化(这一步会清空数据,注意)
$ sudo mkfs.ext4 /dev/vdb              # ext4
# 或
$ sudo mkfs.xfs /dev/vdb               # xfs

# 3. 建挂载点
$ sudo mkdir -p /mnt/data

# 4. 挂载
$ sudo mount /dev/vdb /mnt/data

# 5. 验证
$ df -h /mnt/data
/dev/vdb        492G   28K  468G   1% /mnt/data

已格式化的盘直接挂

# 跨 Linux 系统迁移一块盘?直接 mount 就行(FS 一致的话)
$ sudo mount /dev/vdb /mnt/data

# 指定 FS 类型(可选;mount 通常能自动识别)
$ sudo mount -t ext4 /dev/vdb /mnt/data

# 只读挂载(保护数据安全)
$ sudo mount -o ro /dev/vdb /mnt/data

卸载

$ sudo umount /mnt/data
# 如果有进程占用导致 busy:
$ sudo umount -l /mnt/data    # lazy umount(卡进程时用)
$ sudo fuser -vm /mnt/data    # 查谁占着

注意:是 umount 不是 unmount——这是 Unix 老命名癖好。


4. /etc/fstab:开机自动挂

每次开机手动 mount 太蠢。/etc/fstab 描述"启动时该挂哪些盘":

$ cat /etc/fstab
# <file system>            <mount point>  <type>  <options>           <dump> <pass>
UUID=abc-123-def           /              ext4    defaults,errors=remount-ro 0 1
UUID=987-654-321           /home          ext4    defaults            0      2
UUID=fed-789-cba           /mnt/data      xfs     defaults,noatime    0      2
/swap.img                  none           swap    sw                  0      0
tmpfs                      /tmp           tmpfs   defaults,size=2G    0      0

字段:

  1. 设备:推荐 UUID=...(盘换位置不会失效);用 /dev/sda1 也行但脆
  2. 挂载点/mnt/data 这种路径
  3. fs 类型ext4 / xfs / auto
  4. 选项:见下面
  5. dump:备份相关(一般 0)
  6. pass:fsck 顺序(/ = 1,其他 = 2,不检查 = 0)

拿到 UUID

$ sudo blkid /dev/vdb
/dev/vdb: UUID="abc-123-def..." TYPE="ext4"

# 或者
$ lsblk -f

常用挂载选项

选项 含义
defaults rw,suid,dev,exec,auto,nouser,async
noatime 强烈推荐:不更新文件 access 时间,能减少 30% IO
nodev 不让这个 fs 上有设备文件(安全)
nosuid 忽略 suid bit(安全)
noexec 不允许执行(适合 /tmp 等用户上传目录)
ro / rw 只读 / 读写
discard SSD:删文件时通知设备做 TRIM

noatime 几乎免费提性能——大多数应用根本不在意 atime。

改完测试不重启

# 检查语法
$ sudo mount -a

# 看是否所有 fstab 条目都成功
$ findmnt --verify

mount -a 会按 fstab 重挂所有当前没挂的。如果挂载错的语法被解析到 systemd,开机会卡——所以改完一定 mount -a 测一遍

救场技巧:fstab 写错导致开机卡死,可以从 grub 进 single user 模式,或者在挂载点选项后加 nofail 让它失败也不阻塞启动。


5. 几个"伪文件系统"

不是所有挂载点都对应真实硬件——很多是内核虚拟出来的

$ findmnt | head
TARGET           SOURCE    FSTYPE
/                /dev/sda1 ext4
├─/proc          proc      proc        ← 进程信息(看上篇)
├─/sys           sysfs     sysfs       ← 硬件 / 驱动
├─/dev           devtmpfs  devtmpfs    ← 设备节点
├─/dev/shm       tmpfs     tmpfs       ← 共享内存
├─/run           tmpfs     tmpfs       ← 运行时状态(PID 文件等)
├─/sys/fs/cgroup cgroup2   cgroup2     ← 容器/调度组
└─/proc/sys/fs/binfmt_misc binfmt_misc binfmt_misc

它们在内存里,不占磁盘——重启什么都没了。/tmp 在很多发行版(Fedora、Ubuntu 22+)默认就是 tmpfs——你写 10G 到 /tmp 会占 10G 内存而不是磁盘,机器轻易 OOM。

# 看你的 /tmp 是不是 tmpfs
$ findmnt /tmp
TARGET SOURCE FSTYPE OPTIONS
/tmp   tmpfs  tmpfs  rw,nosuid,nodev,size=2G

是 tmpfs 的话,要传大文件绝对不要走 /tmp,用 /var/tmp/home


6. swap:磁盘当内存用

swap 是"内存不够时把不活跃页扔磁盘"的兜底。不是必须——但对 1-2G 小机器很有用(参考前面阿里云 1G 救命那次)。

加 swap 文件(不需要单独分区)

$ sudo fallocate -l 2G /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile

# 验证
$ swapon --show
NAME      TYPE  SIZE USED PRIO
/swapfile file    2G   0B   -2

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           2.0Gi       1.1Gi       213Mi        21Mi       720Mi       734Mi
Swap:          2.0Gi          0B       2.0Gi

# 让开机也挂上
$ echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

swap 跟内存平衡:vm.swappiness

$ cat /proc/sys/vm/swappiness
60         # 默认 60

# 服务器建议调低,让内核优先用内存
$ echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
$ sudo sysctl -p

值范围 0-200。低 = 不轻易 swap;高 = 容易 swap。SSD 时代不要怕 swap,比 OOM 死掉好。


7. LVM 一句话扫盲

云上你不一定碰到,但家用服务器 / 物理机经常看到挂载点是 /dev/mapper/vg0-root 这种——这是 LVM(Logical Volume Manager)。

LVM 加了一层抽象:

物理硬盘 (PV: physical volume)
    └─ 卷组 (VG: volume group) = 一堆 PV 合并
            └─ 逻辑卷 (LV: logical volume) = 从 VG 切一块出来当"盘"用

好处:

  • 可以在线扩容(把 LV 加大 5G,文件系统接着扩,不用重启)
  • 可以跨多块物理盘虚拟成一个大盘
  • 支持快照(mysqldump 前先 snap,备份完即时回滚)
# 看 LVM 现状
$ sudo pvs              # 物理卷
$ sudo vgs              # 卷组
$ sudo lvs              # 逻辑卷

# 在线扩 /data:先扩 LV,再扩文件系统
$ sudo lvextend -L +10G /dev/vg0/data
$ sudo resize2fs /dev/vg0/data      # ext4
$ sudo xfs_growfs /mnt/data         # xfs

云上一般不用 LVM(云盘本身能在线扩),但物理机 / OpenStack 旧实例会有。看到 /dev/mapper/... 你就知道下面是 LVM。


8. 实战清单:刚买一块新数据盘怎么挂

# 1. 看是哪个设备名
$ lsblk
# 找到那个还没 MOUNTPOINTS 的 disk,比如 /dev/vdb

# 2. 看清楚不是误识别(防止误格式化系统盘!)
$ sudo blkid /dev/vdb     # 应该没输出(未格式化)

# 3. 选 fs 格式化
$ sudo mkfs.ext4 -L data /dev/vdb     # -L 加 label 方便后续识别

# 4. 建挂载点 + 挂
$ sudo mkdir -p /mnt/data
$ sudo mount /dev/vdb /mnt/data

# 5. 拿 UUID 写 fstab(用 UUID 不用 /dev/vdb,避免插拔顺序变了开不了机)
$ UUID=$(sudo blkid -s UUID -o value /dev/vdb)
$ echo "UUID=$UUID /mnt/data ext4 defaults,noatime 0 2" | sudo tee -a /etc/fstab

# 6. 验证开机也能挂
$ sudo umount /mnt/data
$ sudo mount -a
$ df -h /mnt/data        # 又出现了 → fstab 没写错

整个流程 5 分钟。值得熟练。


9. 现在做一件事

# 1. 看你机器目前所有挂载点
$ findmnt -t notmpfs,devtmpfs,proc,sysfs,cgroup2

# 2. 看哪些盘空间最紧张
$ df -h | sort -k5 -hr | head

# 3. 看你的 / 是什么文件系统、哪些挂载选项
$ findmnt /

# 4. 看 swap 现状
$ free -h
$ swapon --show

# 5. 如果是云上 SSD,看 / 是否启用了 discard
$ findmnt -o SOURCE,TARGET,FSTYPE,OPTIONS / | grep -o discard || echo "未开 discard"

理解你脚下踩的"地板"长什么样——这是日常救火的基本功。


下一篇archive-rsync——tar / gzip / zstd / rsync 怎么打包、压缩、增量同步;同一份数据从笔记本同步到服务器要 30 秒还是 3 小时,区别就在这几个命令的选项里。