☰
Linux文件系统选型与实战:ext4、xfs、btrfs、f2fs对比
2026/9/29 1:08:39 网站建设 项目流程

手上经手的机器一多,Linux 文件系统这件事就绕不过去。装系统时默认选 ext4,数据库服务器上别人又劝你用 xfs,NAS 玩家张口闭口 btrfs 快照,嵌入式板子上的 SD 卡还非得 f2fs 才扛得住反复写日志。看着都是 mkfs、mount、df 几条命令,背后却是完全不同的数据组织方式、日志策略、空间分配逻辑和故障恢复习惯。Linux 文件系统不只是“把文件放进去”的容器,它决定了断电后目录还在不在、一块盘能不能在线扩容、删了大文件为什么空间不释放、解压出来中文名为什么全变问号。ext4、xfs、btrfs、f2fs 这些名字,在服务器运维、桌面迁移、虚拟机安装、嵌入式开发、容器底座里反复出现。刚接触的人容易只记命令,踩过几次坑之后才会明白:选文件系统,本质上是在稳定性、性能、可维护性和恢复成本之间做取舍。下面我按实际干活顺序,从 VFS 到格式化参数,再到扩容、排障和选型,把 ext4、xfs 以及周边文件系统一次讲透,适合刚装 Linux 的新手,也适合需要给生产盘做决定的运维和开发。

1. 从VFS到磁盘:Linux文件系统到底在干什么

1.1 为什么同一块盘换个文件系统就像换台机器

很多人第一次感受到文件系统差异,是在同一台机器上换盘测试。一块 SATA SSD,ext4 下顺序写能跑满,换成 xfs 后大文件并行写更稳,换 btrfs 做快照很舒服但跑数据库又可能因为 CoW 碎片化掉性能。磁盘硬件没变,内核版本没变,变的只是文件系统这层“账本”的记账方式。ext4 像一本用了很多年的老账本,索引成熟、兼容性好、修复工具多;xfs 更像为高并发和大文件设计的分区账本,分配组多、延迟分配激进,擅长并行追加;btrfs 则像带版本管理的账本,任何修改先写新块,旧块保留,所以快照几乎瞬间完成,但空间回收和碎片整理要额外操心。

从内核角度看,Linux 并不是直接让应用程序读写磁盘扇区。应用程序调用 open、read、write、close,进入 VFS 这一层统一接口,再由具体文件系统 ext4、xfs、btrfs 把请求翻译成块设备能理解的读写。VFS 让同一个 /home 目录下可以挂 ext4,/data 可以挂 xfs,/boot 可以挂 vfat,用户和大多数程序根本感觉不到差异。也正因如此,文件系统可以像插件一样更换,但每种插件的脾气完全不同。ext4 的 inode 数量通常在 mkfs 时就固定下来,小文件极多时可能先耗尽 inode 而不是空间;xfs 的 inode 动态分配,不容易因为 inode 数量卡死,但目录结构极度膨胀时修复更慢;btrfs 的子卷和快照让回滚很方便,但快照不删除源数据,空间会悄悄被旧版本占住。

我在虚拟机里做过对比:同样 40GB 虚拟盘,ext4 默认格式化后可用空间比 xfs 略多,因为 ext4 默认给 root 保留 5% 空间,xfs 没有这个保留比例;但 xfs 在大目录下 ls 和并行创建文件时更从容。这个差异不是玄学,是文件系统设计目标不同。选型时别只问“哪个最快”,要先问“这块盘要放什么、会不会经常扩容、断电概率高不高、有没有人懂修复”。对普通桌面和一般服务器,ext4 仍然是默认答案;对数据库、日志、大文件存储,xfs 往往更合适;对需要快照和校验的个人 NAS,btrfs 可以玩,但要接受维护成本。

1.2 VFS、页缓存与sync:一次write到底走了哪些路

一次 write 调用并不是直接落盘。程序把数据交给内核后,VFS 先找到对应文件的 inode 和地址空间,数据通常先写进页缓存,页缓存是内存里的脏页集合。内核会根据 dirty_ratio、dirty_background_ratio 等参数决定什么时候回写磁盘。这样做的好处是合并小写、提高吞吐,坏处是机器突然断电时,最近几秒的数据可能还在内存里。sync 命令的作用就是要求内核把脏页刷到块设备,fsync 则针对单个文件,fdatasync 只保证数据部分,不一定刷元数据。很多人以为执行了 sync 就绝对安全,其实还要看磁盘缓存和写屏障设置。如果挂载时用了 barrier=0 或磁盘阵列缓存没有掉电保护,sync 返回后数据仍可能停在硬件缓存里。

VFS 下面还有几个关键对象:superblock 描述整个文件系统,inode 描述文件元数据和数据块位置,dentry 描述目录项,file 描述打开的文件实例,file_operations 是一组函数指针,具体文件系统通过它实现 read、write、mmap、fsync。内核模块可以注册自己的 file_operations,这也是为什么一些监控、加密、审计方案能在 VFS 层拦截读写。普通用户不用改内核,但理解这层结构后,排查问题会清晰很多:df 看的是 superblock 统计,ls -i 看的是 inode 编号,stat 看的是 inode 元数据,dmesg 里的 I/O error 往往来自块层或文件系统层。

页缓存还带来一个常见现象:复制大文件时内存被占满,free 显示 available 很少,但程序还能跑。那不是内存泄漏,是页缓存吃掉了空闲内存,需要时会自动回收。sync 之后 free 里的 buff/cache 不一定马上下降,因为缓存页仍可复用。真正要关心的是脏页比例和回写延迟。服务器上如果发现 iowait 高、writeback 进程忙,先看 /proc/meminfo 的 Dirty、Writeback,再查 vm.dirty_* 参数。数据库这类需要强一致的应用会自己调用 fsync 或 O_DIRECT 绕过页缓存,但 O_DIRECT 对对齐有要求,不是所有文件系统都一样宽容。ext4 和 xfs 对 O_DIRECT 支持都不错,btrfs 在某些场景下表现不同。理解 write 到落盘的链路,才能明白为什么“写入成功”不等于“断电后还在”。

1.3 根文件系统、挂载树和/etc/fstab的协作方式

Linux 启动时,内核先挂载一个临时根文件系统,通常是 initramfs。initramfs 里带着必要的驱动和工具,负责找到真正的根分区,检查文件系统,再 switch_root 切换到真正的根。根文件系统可以是 ext4、xfs、btrfs,也可以是只读的 SquashFS 加 overlayfs 可写层,嵌入式设备常用后者。根文件系统挂载参数写在内核命令行 root=UUID=... rootfstype=ext4 里,系统起来后 /etc/fstab 负责挂载其他分区,比如 /home、/data、swap。fstab 写错是新手最容易遇到的开机失败原因之一,常见的是 UUID 抄错、文件系统类型写错、挂载点不存在、选项里多了空格。

挂载树是一棵从 / 开始的树,任何文件系统都可以挂到某个目录上。挂载后,原目录下的内容会被隐藏,卸载后重新出现。这个特性有人用来做临时覆盖,也有人不小心把数据“弄丢”,其实只是被挂载点遮住了。/proc、/sys、/dev、/run 这些不是普通磁盘文件系统,proc 和 sys 是内核虚拟文件系统,tmpfs 放在内存里,devtmpfs 由内核管理设备节点。df -hT 能看到每个挂载点的类型和容量,findmnt 更直观,lsblk -f 则从块设备角度展示分区、文件系统、UUID、挂载点。排查“根分区满了”时,先 df -hT /,再 du -xhd1 / 逐层找,注意 -x 限制在同一文件系统内,避免跨挂载点统计。

/etc/fstab 的第六列是 fsck 顺序,根文件系统通常是 1,其他 ext4/xfs 分区可以写 2 或 0。xfs 虽然用 xfs_repair 而不是 fsck,但 fstab 里仍可写 0 表示不自动检查。现在很多发行版改用 systemd 的 mount unit 和生成器,fstab 仍是兼容入口。改 fstab 前先备份,改完执行 mount -a 测试,不要直接重启赌运气。如果挂载失败,系统可能进入 emergency mode,这时输入 root 密码进入维护,检查 journalctl -xb、blkid、fstab 内容。根文件系统一旦损坏,修复要卸载或从救援模式进行,ext4 用 fsck.ext4 -f,xfs 用 xfs_repair,btrfs 先用 btrfs check --readonly 看报告,别一上来就写修复。

2. ext4、xfs、btrfs、f2fs逐项拆解:特性、寿命与适用场景

2.1 ext4:稳定、通用、能缩容的默认答案

ext4 是 ext3 的进化版,保留了 ext 系列的兼容性,同时引入 extent、延迟分配、多块分配、日志校验、在线碎片整理等特性。extent 用一段连续块范围描述文件数据,取代传统块映射,减少大文件元数据开销;延迟分配让内核先收集写入请求再决定落盘位置,降低碎片;日志保证元数据一致性,断电后通常不需要长时间 fsck。ext4 最大文件系统和最大文件都很大,日常使用根本碰不到上限,但它默认 inode 数量在 mkfs 时确定,小文件海量场景要提前加 inode 或选 xfs。

ext4 的日志模式有 data=journal、data=ordered、data=writeback。默认 ordered 只记录元数据日志,数据在元数据提交前写入,兼顾安全和性能。data=journal 连数据也写日志,最安全但最慢;writeback 只保证元数据,数据可能旧,适合对一致性要求不高的场景。挂载选项里 noatime 很常用,避免每次读文件都更新访问时间,减少写放大;nodiratime 类似;discard 用于 SSD 在线 TRIM,但有些盘上会卡顿,可以改用 fstrim.timer 定期执行。barrier=1 默认开启,保证写顺序,除非有掉电保护缓存否则别关。

ext4 最大的优势是工具链成熟。e2fsck、resize2fs、tune2fs、dumpe2fs、debugfs、e4defrag 覆盖了检查、扩容、收缩、调参、调试、碎片整理。ext4 支持在线扩容,也支持离线收缩,这是 xfs 没有的能力。你可以把 500GB 的 ext4 分区缩到 200GB,再分新分区,前提是先卸载并做完整 e2fsck。收缩步骤不能反,先 resize2fs 缩小文件系统,再调整分区大小,否则分区表改了而文件系统还以为自己更大,直接损坏。生产环境做收缩前一定备份,别拿唯一副本练手。ext4 的 fsck 在大分区上可能很慢,但至少能修。桌面、通用服务器、启动盘、大多数虚拟机,ext4 都不会出错。

2.2 xfs:大文件与高并发下的性能选手

xfs 最早来自 SGI,天生为 64 位高吞吐设计,现在在 RHEL 系发行版里是默认文件系统之一。它采用分配组机制,把文件系统分成多个 AG,每个 AG 有自己的空闲空间和 inode 管理,多个线程可以并行分配,减少锁竞争。延迟分配、B+树索引、动态 inode、日志写在独立区域,让 xfs 在大文件顺序写、大目录并行创建、混合读写场景里表现很好。数据库数据文件、日志文件、视频存储、备份归档,这些场景用 xfs 通常比 ext4 更从容。

xfs 的 inode 是动态分配的,不需要像 ext4 那样预先决定 inode 数量,所以小文件极多时不容易因为 inode 耗尽而写不进去。但目录项过多时,xfs_repair 可能消耗大量内存和时间,修复成本比 ext4 高。xfs 不能收缩,这是选型时最容易忽略的限制。分区做大了只能扩,不能缩。要缩小只能备份数据、删除分区、重建小文件系统、再恢复。因此给 xfs 分区时,别一上来就把整块盘分完,留一点未分配空间,以后至少还能扩别的分区。xfs 支持在线扩容,挂载状态下执行 xfs_growfs /mountpoint 即可,底层分区要先扩大,比如用 growpart 或 parted。

xfs 的日志区域在 mkfs 时可以指定大小和位置,通常默认足够。挂载选项里 noatime、nodiratime、logbsize、logbufs 可以调,但没明确瓶颈别乱调。xfs_quota 管理配额,xfs_info 看几何信息,xfs_db 调试,xfs_repair 修复,xfs_admin 改 UUID 和 label。xfs 的 fsck 实际上是 xfs_repair,必须卸载后运行,挂载状态下 xfs_repair 会拒绝。断电后 xfs 通常通过日志恢复,恢复不了才需要 xfs_repair。注意 xfs_repair 对损坏严重设备可能直接清空日志,所以修复前如果能挂载只读,先尽量拷数据。服务器上选 xfs,最好配 UPS 或带掉电保护的阵列缓存,日志恢复再强也怕硬件乱写。

2.3 btrfs:快照与校验很诱人,但别忽略维护成本

btrfs 是写时复制文件系统,任何修改都写新块,旧块保留给快照引用。这带来几个杀手级功能:子卷、快照、发送接收、数据校验和、内建 RAID、压缩、在线碎片整理。个人 NAS 上做每日快照,误删文件回滚很快;用 btrfs send/receive 做增量备份也很方便。数据校验和能发现静默损坏,scrub 可以后台校验并修复有冗余的块。ext4 和 xfs 默认没有数据校验和,只能靠底层 RAID 和备份发现坏块,这是 btrfs 的明显优势。

但 btrfs 的复杂度也高。CoW 会让数据库、虚拟机镜像这类频繁随机写的文件产生碎片,性能下降,需要 nodatacow 或单独子卷处理。快照不复制数据,但旧数据被快照引用时不能释放,删了源文件空间也不一定回来,要删快照或等引用消失。balance 是 btrfs 维护空间分布的操作,但跑起来可能很慢、很吃 I/O,甚至在某些版本上引发问题,生产环境要谨慎计划。btrfs 的 RAID5/6 长期被认为不够稳定,重要数据别用。RAID1 和 RAID10 相对成熟,但也要配合备份。btrfs check 默认只读,写修复有风险,遇事优先备份可读数据。

我自己的用法是:个人备份盘、文档仓库、需要频繁快照的实验环境可以用 btrfs;数据库主库、高写入日志盘、对延迟敏感的服务盘,我更倾向 ext4 或 xfs。用 btrfs 要养成看 btrfs filesystem usage、btrfs subvolume list、btrfs scrub status 的习惯,别等磁盘满了才发现全是快照。发行版方面,openSUSE 长期默认 btrfs 根分区加 snapper 回滚,Fedora 也提供 btrfs 方案,Ubuntu 安装器也可选。桌面用户用 btrfs 回滚系统更新很舒服,但要理解子卷布局,不然回滚可能把 /home 一起带回旧状态。

2.4 f2fs、overlayfs、tmpfs:嵌入式、容器与内存盘

f2fs 是 Flash-Friendly File System,针对 NAND 闪存设计,考虑擦除块、垃圾回收、磨损均衡。SD 卡、eMMC、UFS 上反复写小文件时,ext4 的日志和元数据更新可能造成写放大,f2fs 的日志结构分配更适合这类介质。Android 设备大量使用 f2fs,嵌入式 Linux 也常见。f2fs 支持在线扩容、快照不直接支持,工具有 fsck.f2fs、dump.f2fs。要注意 f2fs 在突然断电时的行为依赖内核版本和挂载选项,生产设备最好加掉电检测或只读根文件系统。

overlayfs 是联合文件系统,把只读下层和可写上层层叠成一个目录,容器镜像和嵌入式只读根文件系统大量使用。Docker 的存储驱动早期用 aufs,现在常见 overlay2。overlayfs 本身不直接管理磁盘空间,可写层通常放在 ext4 或 xfs 上,所以底层文件系统性能会影响容器。tmpfs 是内存文件系统,/run、/dev/shm 默认就是 tmpfs,重启即失,适合临时文件、共享内存。tmpfs 大小可以限制,别把大日志写进 /dev/shm 把内存吃光。proc、sysfs、devpts、cgroup2 都是内核虚拟文件系统,不占磁盘,但排查进程、设备、容器限制时离不开它们。

还有 vfat、exfat、ntfs 用于 U 盘和跨系统交换,它们不是 Linux 原生日志文件系统,权限和符号链接支持弱。跨系统共享盘建议 exfat 或 ntfs,挂载时注意 uid、gid、umask、iocharset。SquashFS 是只读压缩文件系统,Live CD、恢复系统、嵌入式固件常用。JFFS2、UBIFS 用于裸 NAND,YAFFS 老设备还在用。分布式文件系统如 NFS、CephFS、GlusterFS 是另一层,它们把远程存储挂进 VFS,本地文件系统仍是底座。理解这些边界,遇到“文件系统”这个词时就不会混为一谈。

2.5 一张表看清主流文件系统怎么选

文件系统核心特点在线扩容收缩快照/校验典型场景主要坑点
ext4稳定、兼容好、工具多支持支持离线收缩无内建数据校验和桌面、通用服务器、启动盘、虚拟机inode 数量固定、fsck 大分区慢
xfs高并发、大文件、动态 inode支持不支持无内建数据校验和数据库、日志盘、视频、备份不能缩容、修复吃内存
btrfsCoW、快照、校验和、子卷支持支持部分调整快照和校验和强个人 NAS、桌面回滚、备份碎片、balance 慢、RAID5/6 不稳
f2fs闪存友好、低写放大支持有限无内建快照SD 卡、eMMC、Android、嵌入式断电一致性看版本、工具较少
overlayfs联合挂载、只读层加可写层随底层随底层无容器、只读根文件系统底层文件系统影响性能
tmpfs内存盘、重启即失动态不适用无/run、/dev/shm、临时缓存吃内存、数据不持久

选型没有绝对赢家。普通服务器和桌面,ext4 省心;数据库和大文件,xfs 更合适;要快照回滚,btrfs 有优势;嵌入式闪存,f2fs 值得考虑。真正要避免的是“听别人说 xfs 快就全盘 xfs”,结果后面想缩小分区发现只能重建。

3. 实操:格式化、挂载、扩容与调优一次跑通

3.1 先认清磁盘:lsblk、blkid、parted的安全用法

动手前先确认设备名。lsblk -f 会列出块设备、分区、文件系统、UUID、挂载点,blkid 显示 UUID 和类型,fdisk -l 或 parted -l 看分区表。虚拟机里新增磁盘通常是 /dev/sdb、/dev/vdb 或 /dev/nvme1n1,别把系统盘 /dev/sda 当成新盘格式化。可以用 ls -l /dev/disk/by-id/ 和 by-path 辅助确认。生产环境操作前先记录 lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID,再执行。

分区用 parted 或 fdisk。GPT 适合大于 2TB 的盘和 UEFI 启动,MBR 有 2TB 限制。下面是常见流程:

lsblk -f sudo parted /dev/sdb --script mklabel gpt sudo parted /dev/sdb --script mkpart primary ext4 0% 100% sudo partprobe /dev/sdb lsblk -f /dev/sdb

如果是整盘直接做文件系统,比如 LVM 逻辑卷或云盘,可以不分区,直接 mkfs.ext4 /dev/vdb。分区后一定 partprobe 或重启让内核重读分区表。老手也会用 wipefs -a /dev/sdb1 清掉旧签名,避免系统把旧文件系统 UUID 认出来。注意 wipefs 只清除签名,不抹数据,但足以让旧文件系统不再自动挂载。

3.2 mkfs.ext4参数怎么下:块大小、inode与日志

mkfs.ext4 默认块大小 4K,适合绝大多数场景。小文件极多且总容量不大时,可以考虑 1K 块减少内部碎片,但会限制最大文件大小并可能降低大文件吞吐。大文件顺序写为主,比如视频存储,4K 块足够,别盲目上 64K。inode 数量用 -N 指定,或用 -i 指定每多少字节一个 inode,默认 16384 字节一个。如果目录下有几百万小文件,df -i 会先满,可以用 -i 4096 或 -N 增大 inode 数。格式化时加 -m 1 把 root 保留空间从 5% 降到 1%,数据盘能多出不少可用空间;系统盘保留 5% 有助于防止 root 写满。

sudo mkfs.ext4 -L data -m 1 -i 8192 -E lazy_itable_init=0,lazy_journal_init=0 /dev/sdb1

lazy_itable_init 和 lazy_journal_init 默认开启,后台初始化 inode 表和日志,加快格式化返回。如果希望格式化后立刻达到最佳性能,可以设为 0,但大容量盘会慢很多。日志大小可用 -J size=128 指定,默认根据文件系统大小自动。查看详情:

sudo dumpe2fs -h /dev/sdb1 sudo tune2fs -l /dev/sdb1

tune2fs 可以改 label、UUID、保留块比例、默认挂载选项、日志模式。修改 UUID 要小心 fstab 和引导配置。e4defrag 可以对碎片化文件整理,但 SSD 上通常没必要,反而增加写入。

3.3 mkfs.xfs参数怎么下:AG、日志与扇区

xfs 格式化参数比 ext4 更强调几何。agcount 是分配组数量,默认根据容量自动,通常够用。大容量高并发可适当增加,比如 8、16,但太多会增加管理开销。日志大小用 -l size=128m,日志可以放在内部或外部设备。扇区大小 -s size=4096,通常跟随设备逻辑扇区。4K 物理扇区盘要用正确扇区大小,否则性能下降。强制覆盖用 -f,label 用 -L。

sudo mkfs.xfs -f -L data -d agcount=8 -l size=128m -s size=4096 /dev/sdb1 sudo xfs_info /data

xfs 不需要指定 inode 数量,动态分配。格式化后挂载:

sudo mkdir -p /data sudo mount /dev/sdb1 /data df -hT /data

如果挂载时报 structure needs cleaning,别急着重启,先看 dmesg。可能是日志未重放,或者设备有坏块。xfs_repair -n 只检查不写,确认后再 xfs_repair。

3.4 挂载与fstab:UUID、noatime、discard、nofail

临时挂载用 mount,持久挂载写 /etc/fstab。UUID 比设备名稳定,云盘和虚拟机里设备名可能变。先 blkid /dev/sdb1 拿 UUID,然后写:

UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx /data ext4 defaults,noatime 0 2

xfs 分区类似,第六列可以写 0。noatime 减少读访问时间更新,SSD 和服务器都推荐。discard 开启在线 TRIM,但可能引起延迟尖峰,更稳的做法是去掉 discard,启用 fstrim.timer 每周或每天执行。nofail 表示设备不存在也能开机,适合外接盘和云盘;x-systemd.device-timeout=10 控制等待时间。不要随便用 defaults 里的 auto,如果盘有问题可能导致开机卡住。

sudo mount -a findmnt /data

改 fstab 后一定 mount -a 测试。如果报错,立即修正,别重启。如果已经进不去系统,在 emergency mode 里 mount -o remount,rw / 再改。对于需要网络挂载的 NFS,加 _netdev 和 nofail。

3.5 在线扩容与收缩:ext4能缩、xfs不能缩的坑

扩容前先扩底层分区或逻辑卷。云盘扩容后,growpart /dev/vda 1,然后 ext4 用 resize2fs /dev/vda1,xfs 用 xfs_growfs /。xfs_growfs 的参数是挂载点,不是设备。ext4 在线扩容:

sudo growpart /dev/vda 1 sudo resize2fs /dev/vda1

xfs 在线扩容:

sudo growpart /dev/vda 1 sudo xfs_growfs /

收缩是危险操作。ext4 收缩必须卸载,先 e2fsck -f,再 resize2fs 目标大小,最后调整分区。顺序是文件系统先缩,分区后缩。xfs 不支持收缩,只能备份重建。btrfs 可以调整设备大小,但也要看子卷和 RAID 配置。如果分区已经占满整盘,xfs 无法缩小,所以我在给数据库盘做 xfs 时习惯留 10% 未分配空间,以后扩容或调整更灵活。

3.6 sync、fsync、barrier与TRIM:数据落盘不是一条命令的事

sync 刷所有脏页,但通常不等待硬件缓存。fsync 等待指定文件数据和元数据落盘,数据库提交时常用。fdatasync 只等数据,不等部分元数据。dd 测试时加 conv=fsync 才能在结束前强制落盘。挂载选项 barrier=1 保证写屏障,barrier=0 可能提升性能,但断电风险高。SSD 的 TRIM 可以用 fstrim -av 测试,定期执行:

sudo fstrim -av systemctl status fstrim.timer

ext4 和 xfs 都支持在线 discard 和定期 fstrim,后者更可控。还有 commit=60 控制 ext4 日志提交间隔,默认 5 秒,调大减少写但增加断电丢失窗口。数据库别乱调。写缓存方面,磁盘的 write cache 可以用 hdparm -W 查看和设置,但关掉会大幅降性能,最好依赖 UPS 和带电池的阵列卡。理解这些选项后,你会明白“数据写进去了”和“数据安全落盘了”是两回事。

4. 故障排查与常见问题:从“磁盘满了”到“解压乱码”

4.1 df和du不一致:deleted-open、inode耗尽与保留块

df -h 显示磁盘满,du -sh 却统计不出那么多,常见原因是文件被删除但进程仍打开。Linux 中删除文件只是去掉目录项,inode 和数据块要等打开的文件描述符关闭才释放。用 lsof +L1 或 lsof | grep deleted 找。重启对应进程或清空 /proc/ /fd 里的文件描述符即可释放。另一种是挂载点覆盖,根分区某个目录其实挂了别的盘,du 不加 -x 会跨文件系统统计。df -i 看 inode 使用率,ext4 小文件多时可能 inode 先满,报 No space left on device 但 df -h 还有空间。

ext4 默认保留 5% 给 root,df 显示已用 100% 时,普通用户写不进去,root 还能写。tune2fs -m 1 可以降低保留比例。日志文件、快照、未删除的临时文件也会占空间。btrfs 要看 btrfs filesystem usage,因为 df 显示可能不准确,快照和元数据会占额外空间。xfs 的 df 统计通常直接,但配额和项目配额会影响。遇到空间问题,先 df -hT、df -i、du -xhd1、lsof +L1 四件套,再决定删什么、扩什么。

4.2 dmesg、smartctl与fsck/xfs_repair的使用边界

磁盘故障第一现场在 dmesg。常见关键字:I/O error、EXT4-fs error、XFS corruption、blk_update_request、medium error、ata bus error。先 dmesg -T | tail -100,再看 journalctl -k。坏道和线缆问题用 smartctl -a /dev/sdb 看 SMART,注意 reallocated sector、pending sector、CRC error。如果盘已经在报错,优先备份数据,不要反复 fsck 加重磨损。

ext4 修复用 fsck.ext4 -f /dev/sdb1,必须卸载。e2fsck -p 自动修复安全项,-y 全部回答 yes,-n 只检查。xfs 用 xfs_repair,先 -n 检查,再实际修复,必须卸载。btrfs 用 btrfs check --readonly,写修复风险高。修复前尽量只读挂载拷数据,或者用 ddrescue 做镜像再修。注意 fsck 在挂载状态运行会损坏文件系统,现代工具会阻止,但不要强行。LVM 快照可以给修复留后路,但快照空间要够。

4.3 解压乱码不一定是文件系统坏了:编码、locale与挂载iocharset

解压 zip 后中文名乱码,九成不是 ext4 或 xfs 的问题,而是 zip 文件名编码。Windows 下用 GBK/CP936,Linux 默认 UTF-8,unzip 旧版本不会自动转。可以用 unzip -O CP936 file.zip,或者 7z x file.zip,再用 convmv -f gbk -t utf8 -r --notest 目录。locale 设置也影响显示,locale 查看当前语言环境,必要时安装 zh_CN.UTF-8。文件系统本身如果挂载 vfat/exfat/ntfs,需要 iocharset=utf8,否则中文文件名可能显示异常。ext4 和 xfs 不存文件名编码,只存字节,显示由上层决定。

另一种乱码是挂载了错误的字符集或解压工具版本太老。Linux 解压 7z 用 7z x,rar 用 unrar,tar.gz 一般无编码问题。文本文件乱码是内容编码,用 file、iconv 判断和转换,跟文件名不是一回事。排查顺序:先看 locale,再看工具是否支持编码参数,最后才怀疑文件系统。如果 ext4 元数据坏了,通常不是乱码而是输入输出错误、目录项丢失。

4.4 虚拟机、WSL与嵌入式:qcow2、跨系统挂载和只读根文件系统

虚拟机里安装 Linux,虚拟磁盘文件放在宿主 ext4/xfs 上。qcow2 是写时复制格式,宿主文件系统碎片和快照会影响虚拟机性能。KVM 下用 virtio-blk 或 virtio-scsi,比 IDE 快很多。给虚拟机磁盘做 ext4/xfs 与物理机没区别,但要注意 aio、cache 模式,cache=none 通常更安全。WSL 2 使用虚拟化内核,Windows 文件通过 9p 协议挂到 /mnt/c,跨系统访问大量小文件很慢。项目代码放在 Linux 文件系统内,比如 ~/project,比放在 /mnt/c 下快得多。WSL 版本过旧会提示升级内核,按发行版文档更新即可。

嵌入式 Linux 常用只读根文件系统加 overlayfs 可写层,底层 SquashFS 或 ext4 只读挂载,数据分区用 ext4 或 f2fs。SD 卡容易因断电损坏,建议挂载时加 sync 写策略、noatime,数据目录用 f2fs,根文件系统只读。UBIFS 用于裸 NAND,JFFS2 更老。Android 的 data 分区常用 f2fs 或 ext4,system 分区只读。国产 Linux 发行版和桌面环境对 ext4/xfs 支持都很成熟,安装时默认选 ext4 基本不会错。

4.5 常见问题速查表

现象可能原因快速排查处理建议
df 满但 du 不大deleted-open 文件、挂载覆盖、快照lsof +L1、findmnt、btrfs subvolume list重启进程、清快照、修正挂载
No space left 但 df -h 有余inode 耗尽df -i清理小文件,重建时加 inode
开机 emergency modefstab 错误、UUID 变、盘缺失journalctl -xb、blkid改 fstab,加 nofail
ext4 报 error断电、坏块、线缆dmesg、smartctl卸载后 e2fsck,先备份
xfs 报 corruption断电、坏块、缓存dmesg、xfs_repair -n卸载后 xfs_repair
解压中文乱码zip 编码、localelocale、unzip -O用 7z 或 convmv 转换
SSD 越来越慢未 TRIM、写放大fstrim -av启用 fstrim.timer
扩容后空间没变只扩分区没扩文件系统lsblk、dfresize2fs 或 xfs_growfs
xfs 想缩容xfs 不支持收缩xfs_info备份重建,或改用 ext4
btrfs 空间不释放快照引用、元数据btrfs filesystem usage删快照、balance 谨慎执行

5. 选型、维护与面试:把文件系统当成长期资产

5.1 服务器、桌面、NAS、嵌入式怎么选

服务器选型先看业务。数据库主库、高并发日志、视频存储,xfs 往往更合适,因为动态 inode、大文件并行和延迟分配有优势,但必须接受不能缩容,并且最好有 UPS 或掉电保护缓存。通用 Web 服务器、应用服务器、编译机,ext4 省心,工具多,出问题好修,在线扩容方便。容器节点底层用 ext4 或 xfs 都行,overlay2 在两者上都成熟,xfs 需要 ftype=1,现代 mkfs.xfs 默认就是。Kubernetes 节点建议单独数据分区,避免镜像和日志写满根分区。

桌面和笔记本,ext4 默认足够。想玩系统快照回滚,btrfs 加 snapper 很舒服,但要理解子卷和空间占用。个人 NAS,如果主要存文档、照片,需要快照和校验,btrfs RAID1 可以考虑,但一定要有异地备份,别把 RAID 当备份。嵌入式设备,SD 卡/eMMC 用 f2fs 或 ext4,根文件系统只读加 overlay,数据分区单独挂载。U 盘和跨系统移动盘用 exfat,兼容 Windows、macOS、Linux。国产化环境里,整机厂商常用 ext4 或 xfs,安装器和恢复工具都支持,选默认通常最稳。

5.2 备份、快照、监控与升级路线

文件系统不是备份。RAID 只防盘坏,不防误删、勒索、火灾。备份策略至少 3-2-1:三份数据,两种介质,一份异地。ext4 和 xfs 可以用 rsync、borg、restic 做文件级备份,btrfs 可以用 send/receive 做增量快照。LVM 快照可以给 ext4/xfs 做短暂一致性备份,但快照空间要预留,写多了会满。数据库要么用物理备份工具,要么在备份前锁表或做快照,别直接 copy 正在写的 ibd 文件。

监控要盯容量、inode、I/O 延迟、错误日志。df -hT、df -i、iostat -x 1、dmesg、smartctl 是基础。ext4 看 dumpe2fs -h 的 Free blocks、Free inodes;xfs 看 xfs_info 和 xfs_quota;btrfs 看 btrfs filesystem usage 和 scrub status。升级内核或发行版前,确认文件系统工具版本匹配,比如新内核特性需要新版 e2fsprogs 或 xfsprogs。扩容、收缩、修复前先备份,别在唯一副本上操作。定期做恢复演练,备份没恢复过就等于没有。

5.3 面试常问的文件系统问题与回答思路

面试里文件系统问题很常见。问 ext4 和 xfs 区别,可以从 inode 分配、日志、扩容收缩、适用场景回答:ext4 固定 inode、支持离线收缩、工具成熟;xfs 动态 inode、不支持收缩、大文件并发强。问 df 和 du 不一致,答 deleted-open、挂载覆盖、保留块、快照。问 sync 和 fsync,答 sync 刷所有脏页,fsync 等待单文件落盘,fdatasync 不刷部分元数据。问 inode 是什么,答存元数据和数据块指针,目录也是文件,文件名在目录项。问软硬链接区别,答硬链接共享 inode,软链接是独立文件存路径。问日志模式,答 journal、ordered、writeback 的安全性和性能差异。问根文件系统挂载流程,答 initramfs 找根,switch_root,fstab 挂其他。问文件系统损坏怎么办,答先备份、卸载、只读检查、再修复,ext4 用 e2fsck,xfs 用 xfs_repair,btrfs 谨慎。

回答时别只背命令,讲清楚为什么这么做。比如为什么 xfs_repair 要卸载,因为修复过程需要独占访问;为什么 ext4 收缩要先 e2fsck,因为要确保文件系统一致才能安全移动数据块;为什么 btrfs 快照删除后空间不马上回来,因为还有引用。面试官通常想听的是判断力,不是命令列表。

最后分享一个我自己的习惯:任何一块新盘,先 lsblk -f 和 blkid 记录 UUID,再决定 ext4、xfs 还是 btrfs;数据盘 ext4 用 -m 1 留少点保留块,xfs 留 10% 未分配空间防无法缩容;fstab 改完必须 mount -a;上线前用 fstrim -av、df -i、dmesg 检查一遍。文件系统这层平时没动静,一出事就是数据大事,宁可格式化前多花五分钟想清楚,也别等空间满了、盘坏了、缩不了了再后悔。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询