存储与磁盘管理
Linux 运维基础 · 第十二章 目标:掌握磁盘查看、分区、挂载、LVM 扩容的完整操作
1. 概述#
磁盘是运维不可回避的话题。日志撑爆磁盘、数据库需要扩容、新磁盘需要挂载——这些场景在每个运维的职业生涯中反复出现。
本章从"看"开始,到"扩容"结束,覆盖 df/du/lsblk/fdisk/mount/LVM 全链路。
2. 查看空间#
2.1 df — 文件系统级别#
bash
df -h # 人类可读格式
df -hT # 同时显示文件系统类型
df -i # 查看 inode 使用情况(小文件太多时关注)
df -h / /data /var # 只看指定目录所在文件系统bash
# 典型输出
df -h
# Filesystem Size Used Avail Use% Mounted on
# /dev/sda1 50G 30G 18G 63% /
# /dev/sdb1 100G 75G 25G 75% /data
# tmpfs 7.8G 0 7.8G 0% /dev/shm
# tmpfs 1.6G 1.1M 1.6G 1% /run
# 重点关注
# Use% 接近 100% → 告警
# Avail 持续减少 → 趋势恶化,需排查坑:df 显示还有空间,写文件却报
No space left on device大概率是 inode 耗尽(小文件太多,如 session/缓存/邮件队列把 inode 用光了)。df -h看的是块空间,df -i才看 inode:bashdf -i # IUse% 到 100% 就是 inode 满了 # Filesystem Inodes IUsed IFree IUse% Mounted on # /dev/sda1 3.2M 3.2M 0 100% / ← 块没满,inode 满了 # 定位哪个目录小文件最多 for d in /var/*; do echo "$(find "$d" 2>/dev/null | wc -l) $d"; done | sort -rn | head解决:删掉海量小文件(如清缓存队列),或重建文件系统时调大 inode 密度(
mkfs.ext4 -N)。 注意:xfs 的 inode 是动态分配的,通常不会像 ext4 那样固定耗尽。
2.2 du — 目录级别#
bash
du -sh * # 当前目录下每个文件/目录的总大小
du -sh /* 2>/dev/null # 根目录下一级各占多少(忽略错误)
du -sh /home # 看 /home 目录总大小
# 找大户
du -sh /* 2>/dev/null | sort -rh | head -10 # 磁盘谁占最多
# 深入排查
du -h --max-depth=1 /var/log/ # 只看一层深度
du -h --max-depth=1 /data/ | sort -rh | head
# 找大文件
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null2.3 df vs du 不一致#
bash
# df 显示 80G,du 加起来才 50G——30G 去哪了?
# 答案:见第 02 章"删文件的本质"
# 有进程持有已删除文件的句柄
lsof +L1 | awk '{print $1, $7}' | sort -nrk2 | head
# 找出"幽灵文件",重启对应进程即可释放3. 查看块设备#
3.1 lsblk — 磁盘/分区树#
bash
lsblk # 树形显示所有块设备
lsblk -f # 同时显示文件系统类型和 UUID
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,FSTYPE # 自定义列
# 典型输出
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 50G 0 disk
# ├─sda1 8:1 0 49G 0 part /
# └─sda2 8:2 0 1G 0 part [SWAP]
# sdb 8:16 0 100G 0 disk
# └─sdb1 8:17 0 100G 0 part /data3.2 fdisk — 分区表#
bash
fdisk -l # 列出所有磁盘的分区表
fdisk -l /dev/sdb # 只看某块磁盘
# fdisk 交互式分区
# fdisk /dev/sdc # 进入交互模式
# m = 帮助, n = 新建分区, d = 删除分区
# w = 写入分区表并退出, q = 不保存退出3.3 其他查看命令#
bash
blkid # 查看块设备的 UUID 和文件系统类型
parted -l # 更现代的分区查看工具(支持 GPT)
lsscsi # 查看 SCSI 设备
ls -la /dev/disk/by-uuid/ # 按 UUID 查看磁盘
ls -la /dev/disk/by-id/ # 按设备 ID 查看4. 挂载(mount)#
4.1 mount 基础#
bash
# 查看当前挂载
mount | column -t # 格式化输出
findmnt # 树形显示挂载关系
# 挂载
mount /dev/sdb1 /data # 挂载分区到目录
mount -t ext4 /dev/sdb1 /data # 指定文件系统类型
mount -o ro /dev/sdb1 /data # 只读挂载
# 卸载
umount /data # 按挂载点卸载
umount /dev/sdb1 # 按设备名卸载
# 如果 umount 提示 target is busy
umount -l /data # lazy unmount,立即从文件系统树中移除
fuser -m /data # 查看谁在用这个挂载点
lsof /data # 查看哪些进程打开了文件4.2 /etc/fstab — 开机自动挂载#
bash
cat /etc/fstab
# <file system> <mount point> <type> <options> <dump> <pass>
# /dev/sdb1 /data ext4 defaults 0 2
# UUID=abc... /backup xfs defaults 0 0
# 字段说明
# 1. 设备: /dev/sdb1 或 UUID=xxx 或 LABEL=xxx
# 2. 挂载点
# 3. 文件系统类型: ext4/xfs/...
# 4. 挂载选项: defaults,noatime,nofail ...
# 5. dump(备份标记,0=不备份)
# 6. pass(开机 fsck 检查顺序,0=不检查,1=根分区,2=其他)bash
# 添加 fstab 条目后验证
mount -a # 测试挂载(不会覆盖已有挂载)
# 常用选项
# defaults = rw,suid,dev,exec,auto,nouser,async
# nofail = 设备不存在时不报错(对外部存储很重要)
# noatime = 不更新文件访问时间(减少磁盘 I/O)
# _netdev = 网络设备,等网络就绪再挂载(NFS/iSCSI)4.3 实战:挂载新磁盘#
bash
# Step 1:查看新磁盘
lsblk
# sdc 8:32 0 200G 0 disk ← 新磁盘
# Step 2:分区(如果不需要可跳过,直接格式化整盘)
fdisk /dev/sdc
# n → 新建分区 → 一路回车(用全部空间)→ w
# Step 3:格式化
mkfs.ext4 /dev/sdc1 # ext4
# 或
mkfs.xfs /dev/sdc1 # xfs
# Step 4:创建挂载点
mkdir -p /data
# Step 5:挂载
mount /dev/sdc1 /data
# Step 6:自动挂载
blkid /dev/sdc1 # 获取 UUID
echo "UUID=xxx-xxx-xxx /data ext4 defaults 0 2" >> /etc/fstab
mount -a # 验证5. LVM 基础#
LVM(Logical Volume Manager)在物理磁盘之上加了一层抽象,让你能在线扩容而无需卸载文件系统。
5.1 三层结构#
text
PV (Physical Volume) 物理卷 ← 物理分区或整盘
└── VG (Volume Group) 卷组 ← 多个 PV 组合成池
└── LV (Logical Volume) 逻辑卷 ← 从 VG 中分配的空间,挂载使用一个类比:PV 是硬盘,VG 是硬盘阵列柜,LV 是从柜子里划出来的分区。
5.2 查看 LVM#
bash
pvdisplay # 查看物理卷(或 pvs,简洁版)
vgdisplay # 查看卷组(或 vgs)
lvdisplay # 查看逻辑卷(或 lvs)5.3 扩容逻辑卷#
bash
# 场景:/data 分区快满了,从 VG 还有 50G 空闲,扩容 LV
# Step 1:确认当前大小
df -h /data
# Step 2:LV 扩容
lvextend -L +20G /dev/mapper/vg_data-lv_data
# 或扩展到 100% 的 VG 剩余空间
lvextend -l +100%FREE /dev/mapper/vg_data-lv_data
# Step 3:文件系统扩容(LV 变大了,文件系统还不知道,得单独扩)
# ext4 —— 认设备路径:
resize2fs /dev/mapper/vg_data-lv_data
# xfs —— 认挂载点,且文件系统必须处于挂载状态:
xfs_growfs /data
# Step 4:确认
df -h /data必记的文件系统差异(扩缩容规则)
文件系统 扩容命令 在线扩容 缩小 ext4 resize2fs <设备>支持 支持,但必须先 umount离线操作,且需先缩文件系统再缩 LVxfs xfs_growfs <挂载点>支持(必须挂载着扩) 不支持!只能扩不能缩
- xfs 无法缩小是最常见的坑:分区规划过大想收回空间时才发现退不回来, 唯一办法是备份数据 → 重建更小的文件系统 → 恢复。规划 xfs 时宁可留小点。
- 默认文件系统:RHEL/Rocky/Alma 系默认 xfs,Debian/Ubuntu 系默认 ext4。 建新盘前先想清楚将来会不会需要缩容,需要缩就别用 xfs。
- 命令别记混:
resize2fs收/放 ext4、认设备名;xfs_growfs只放 xfs、认挂载点。
5.4 创建 LVM(从零开始)#
bash
# Step 1:创建 PV
pvcreate /dev/sdc1
# Step 2:创建 VG
vgcreate vg_data /dev/sdc1
# Step 3:创建 LV
lvcreate -L 50G -n lv_data vg_data
# Step 4:格式化
mkfs.ext4 /dev/mapper/vg_data-lv_data
# Step 5:挂载
mkdir -p /data
mount /dev/mapper/vg_data-lv_data /data
echo "/dev/mapper/vg_data-lv_data /data ext4 defaults 0 2" >> /etc/fstab6. Swap#
6.1 查看#
bash
free -h # 看 Swap 大小和使用
swapon --show # 查看所有交换空间6.2 增加 Swap#
bash
# 场景:物理内存不够,临时加 4G Swap
# Step 1:创建 swap 文件
dd if=/dev/zero of=/swapfile bs=1G count=4
# 4G 文件
# Step 2:设置权限
chmod 600 /swapfile # 安全要求
# Step 3:格式化为 swap
mkswap /swapfile
# Step 4:激活
swapon /swapfile
# Step 5:开机自动激活
echo "/swapfile none swap sw 0 0" >> /etc/fstab
# 验证
free -h
swapon --show7. 文件系统修复#
bash
# fsck:文件系统检查与修复
# 使用前必须 umount!
umount /dev/sdb1
fsck -y /dev/sdb1 # -y 自动回答 yes
fsck -n /dev/sdb1 # -n 只检查不修复(安全预览)
# 注意:fsck 只能修复元数据层面的问题,硬件坏道无法修复8. 实战#
实战 1:磁盘谁占最多#
bash
# 快速定位
du -sh /* 2>/dev/null | sort -rh | head -10
# 如果发现 /var 巨大,深入查
du -h --max-depth=1 /var/ | sort -rh | head -10
# 发现 /var/log 很大
du -h --max-depth=1 /var/log/ | sort -rh | head -10
# 发现 nginx 日志 20G
ls -lh /var/log/nginx/
# 马上清理
find /var/log/nginx -name "*.log" -mtime +30 -delete
# 或压缩留存
find /var/log/nginx -name "*.log" -mtime +30 -exec gzip {} \;实战 2:根分区扩容#
bash
# 场景:云服务器购买了更大磁盘,根分区还是老大小
# Step 1:确认新大小
lsblk
# sda 从 50G 变成了 100G
# Step 2:扩展分区
growpart /dev/sda 1 # 对根分区所在的分区号(growpart 属 cloud-utils-growpart 包)
# 注意 growpart 后面是【空格】分区号,不是 /dev/sda1
# 如果是 LVM 根分区(Rocky/Alma 9 默认 VG 名多为 rl / almalinux,用 lvs 确认真实名字)
pvresize /dev/sda1
lvextend -r -l +100%FREE /dev/mapper/rl-root
# -r 参数自动调用 resize2fs(ext4)/xfs_growfs(xfs),省掉手动扩文件系统那步
# Step 3:验证
df -h /实战 3:应急 Swap#
bash
# 场景:数据库 OOM,内存不够,临时加 swap 扛住
dd if=/dev/zero of=/swapfile bs=1G count=8 status=progress
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
# 确认生效
free -h | grep Swap
# 持久化
echo "/swapfile none swap sw 0 0" >> /etc/fstab
# 通知团队,安排扩容内存9. 小结#
| 知识点 | 一句话记忆 |
|---|---|
| df | 文件系统级别,df -h 看块空间,df -i 看 inode |
| inode 耗尽 | 块没满却报 No space → df -i 查 IUse%(小文件太多) |
| du | 目录级别,du -sh /* 找大户 |
| lsblk | 树形看磁盘和分区 |
| mount | mount /dev/sdb1 /data 挂载,/etc/fstab 开机自动挂载 |
| LVM | PV→VG→LV 三层,lvextend + resize2fs(ext4) / xfs_growfs(xfs) 在线扩容 |
| xfs vs ext4 | xfs 只能扩不能缩;ext4 可扩可缩(缩要离线);RHEL 系默认 xfs、Debian 系默认 ext4 |
| df vs du 不一致 | 进程持有已删除文件——lsof | grep deleted |
| Swap | dd + mkswap + swapon 三步创建 |
上一章:十一、网络诊断工具 下一章:十三、服务管理 systemd