🐧 第02章 · 磁盘与文件系统

df du lsblk fdisk mkfs mount fsck

磁盘与文件系统

磁盘满了、挂载掉了、分区要扩容——这是运维每天都要面对的问题。这一章讲清磁盘、分区、文件系统三层概念,以及排障最常用的 df、du、lsblk、mount 等命令。

三层概念:磁盘、分区、文件系统

先分清三个层次,排障才不会乱:

层次 是什么 查看命令 管理命令
磁盘 (Disk) 物理/虚拟块设备 lsblk、fdisk -l fdisk、parted
分区 (Partition) 从磁盘切出的块 lsblk fdisk、parted、mkfs
文件系统 (Filesystem) 分区上建立的目录树 df、blkid mkfs、mount、fsck

易错 df 报告的是文件系统,不是磁盘。一块 193G 的 / 分区里,du 统计的是目录里的文件,"df 说满了,du 加起来对不上"是经典的认知误区——因为 du 只算文件,df 还包含被删但被进程占用的文件、inode 开销和保留块。

查看挂载与使用率:df

df 是磁盘排障第一入口:

df -hT                 # -h 人类可读大小,-T 显示文件系统类型
df -h /                # 只看 / 分区
df -i                  # 查看 inode 使用率(文件很多时,块没用满也可能 inode 用尽)

本机实际输出(节选):

文件系统     类型  容量  已用  可用 已用% 挂载点
/dev/sda1   ext4  193G   15G  179G   8%  /

易错 df 显示 100% 却还能写文件,通常是 root 用户不受 5% 保留块限制;反之 df 低但 df -i 高(inode 用尽)时通常是"海量小文件"(如 GitLab 仓库、Node 的缓存文件)——查 /var/log、/tmp、GitLab 仓库目录。

统计目录大小:du

想知道哪个目录占满磁盘,用 du 从大到小排查:

du -sh /var/www/*          # -s 汇总目录,-h 人类可读,列出各站点大小
du -h --max-depth=1 /var/log    # 逐层看 /var/log 下每个子目录大小
du -sh /                    # 全盘总占用(慢,慎用)

排查"谁占满了磁盘"的标准三步:

du -h --max-depth=1 / | sort -rh | head    # 第一层找大项
du -h --max-depth=1 /var | sort -rh | head # 逐层下钻
du -sh /var/log/* | sort -rh               # 定位到具体目录

du 会扫全量文件,很慢;配合 --max-depth 先粗后细,避免在一层里卡死。

易错 du 算的是磁盘上的实际占用,ls -l 显示的是文件逻辑大小。稀疏文件、压缩文件、目录项本身都会让两者不一致。du 扫描大 Git 仓库或 node_modules 时非常慢,排障期间尽量用 --max-depth 控制范围。

分区查看:lsblk 与 fdisk

lsblk 看结构,fdisk -l 看分区表细节:

lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,UUID   # 结构+文件系统+UUID
fdisk -l /dev/sda            # 打印 sda 的分区表信息
blkid                        # 列出所有分区 UUID(挂载时用)

UUID 是文件系统的唯一标识,/etc/fstab 挂载时推荐用 UUID 而不是设备名,因为设备名(如 sda1)会因插拔顺序变化,而 UUID 不变。

挂载与卸载:mount 与 umount

mount 把文件系统挂到目录上,umount 卸载:

mount | grep -E "ext4|vfat"     # 查看当前挂载的磁盘文件系统
mount /dev/sdb1 /mnt/data       # 手动挂载(临时用,重启失效)
umount /mnt/data                # 卸载(忙时会失败,见下方提示)
mount -o remount,rw /           # 重挂载为可写(只读根救急常用)

易错 umount: target is busy 是经典报错——有进程正在使用该挂载点。可用 fuser -mv /mnt/data 找出占用进程,或 lsof +D /mnt/data;确认安全后再卸载。不要随意 umount -l(懒卸载),它虽能强制成功但会留下"幽灵挂载"。

分区与格式化:fdisk 与 mkfs(慎重操作)

给新磁盘分区、建文件系统是一次性且不可逆的操作,必须确认设备名再动手:

fdisk /dev/sdb         # 交互式分区:p 打印,n 新建,w 写入,q 不保存退出
mkfs.ext4 /dev/sdb1    # 在第1个分区上建 ext4 文件系统(清空数据!)
mkfs.xfs /dev/sdb1     # xfs 大容量/高并发场景常用
# fdisk 典型流程(新盘 sdb)
p        # 查看当前分区表
n        # 新建分区,p 主分区,1,起始/结束直接回车用默认
w        # 写入分区表退出

安全警告 mkfs 会清空整个分区/磁盘。执行前务必用 lsblk 确认目标设备,确认没有数据;生产环境先 cp/rsync 备份。本机生产系统盘是 /dev/sda,扩容/格式化类操作一律先截图备份分区表 sfdisk -d /dev/sda > backup.sfdisk,恢复用 sfdisk /dev/sda < backup.sfdisk。

文件系统检查:fsck

系统异常关机、断电后,文件系统可能不一致,用 fsck 修复。必须卸载后再检查:

umount /dev/sdb1
fsck -y /dev/sdb1      # -y 自动回答 yes(参数统一用 -f 强制检查 + -y 自动修复)
tune2fs -l /dev/sda1   # 查看 ext4 的挂载次数、上次检查时间、保留块

易错 不要对已挂载的分区运行 fsck(/ 根分区只有在救援模式/只读挂载时才能 fsck)。错误运行会损坏文件系统。Ubuntu 在启动时若检测到异常,会自动进入修复或提示手动 fsck。

开机自动挂载:/etc/fstab

/etc/fstab 定义开机自动挂载。格式为 设备 挂载点 类型 选项 dump fsck:

cat /etc/fstab
# 例:/dev/sda1   /   ext4   errors=remount-ro   0 1

修改后用 mount -a 先验证,避免因 fstab 写错导致开机进不去:

# 加一行后立刻验证,再重启
echo "/dev/sdb1 /mnt/data ext4 defaults 0 2" >> /etc/fstab
mount -a                # 若报错说明 fstab 有误,立刻改回

易错 fstab 一行写错(UUID 不存在、路径不存在),重启会进"emergency mode"。改完必须执行 mount -a 先试错,一旦报错马上修正,别直接 reboot。

常见故障案例

磁盘满了导致服务写不进日志:Node 应用 /var/www/bangdream(端口 3000)忽然 500,df -h 显示 / 100%。先删大文件或日志,再看服务恢复。排查顺序:

df -h                       # 哪个挂载点满了
du -h --max-depth=1 /var | sort -rh | head   # 定位大目录
journalctl --vacuum-size=500M   # 老日志可能就占几 G,直接清常是我站首因

添加新数据盘(挂载新分区):

lsblk                       # 确认新盘(如 sdb)
fdisk /dev/sdb              # 分区
mkfs.ext4 /dev/sdb1         # 格式化
mkdir -p /mnt/data          # 建挂载点
mount /dev/sdb1 /mnt/data   # 挂载
# 写入 fstab 并验证
echo "UUID=$(blkid -s UUID -o value /dev/sdb1) /mnt/data ext4 defaults 0 2" >> /etc/fstab
mount -a && df -h /mnt/data

易错点

  • df 满 ≠ 磁盘坏:可能是 inode 耗尽、被删文件仍被进程占用(lsof +L1 查)、或保留块。
  • du 与 df 对不上:正常现象,du 按目录算,df 按文件系统算。
  • 对已挂载分区跑 fsck:前必须先 umount。
  • fstab 写错直接重启:务必先 mount -a 验证,否则进 emergency mode。

相关命令

df、du、lsblk、blkid、fdisk、mount、umount、mkfs、fsck、tune2fs、lsof、findmnt。