存储与磁盘
第8章:Linux 存储与磁盘管理
存储是服务器可靠性的基石。本章从块设备基础出发,系统讲解 Linux 存储管理的完整技术栈:fdisk/parted 分区,mkfs 创建文件系统,mount/fstab 持久挂载,LVM 逻辑卷的在线扩容,fsck/dd 故障修复与克隆,以及 smartctl 预测性健康监测。掌握这些技能,你将能从容应对任何磁盘容量危机和存储故障。
8.1 磁盘基础:块设备与信息查看
Linux 中一切皆文件,磁盘也不例外。磁盘以块设备的形式暴露在 /dev/ 目录下。SATA/SAS 磁盘命名为 /dev/sda、/dev/sdb,NVMe SSD 命名为 /dev/nvme0n1、/dev/nvme1n1,分区则在末尾追加数字,如 /dev/sda1、/dev/nvme0n1p1。
# === lsblk — 树状显示块设备 ===
lsblk # 基本树状视图
lsblk -f # 显示文件系统类型和 UUID
lsblk -o NAME,SIZE,TYPE,FSTYPE,MOUNTPOINT,UUID # 自定义列
# 示例输出:
# NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
# sda 8:0 0 500G 0 disk
# ├─sda1 8:1 0 1G 0 part /boot
# ├─sda2 8:2 0 50G 0 part /
# └─sda3 8:3 0 449G 0 part /data
# nvme0n1 259:0 0 1.8T 0 disk
# └─nvme0n1p1 259:1 0 1.8T 0 part /fast
# === blkid — 显示 UUID 和文件系统类型 ===
sudo blkid # 所有块设备
sudo blkid /dev/sda1 # 指定分区
# 输出示例:
# /dev/sda1: UUID="a1b2c3d4-..." TYPE="ext4" PARTUUID="..."
# === df — 磁盘空间使用(已挂载文件系统)===
df -h # 人类可读单位(-h human-readable)
df -hT # 同时显示文件系统类型
df -h /home # 只查看 /home 所在文件系统
df -i # 显示 inode 使用情况(inode 耗尽同样会导致无法写入)
# === du — 目录/文件占用空间 ===
du -sh /var/log # 查看目录总大小
du -sh /var/log/* # 子目录各自大小
du -h --max-depth=1 / # 根目录一层深度
du -sh * | sort -rh | head -20 # 当前目录最大的 20 个文件/目录
# === hdparm — 磁盘详细信息 ===
sudo hdparm -I /dev/sda # 显示磁盘型号、固件版本、支持特性
sudo hdparm -t /dev/sda # 测试磁盘顺序读取速度(不加缓存)
8.2 分区管理:fdisk / parted / gdisk
分区前备份数据: 分区操作是破坏性的。**fdisk/parted 的错误操作会导致数据永久丢失。**在对生产磁盘操作之前,务必确认目标设备名(
lsblk确认),并做好数据备份。对正在使用的系统盘分区需要从 Live CD/USB 启动。
fdisk — 交互式 MBR/GPT 分区
# 启动 fdisk 交互式界面
sudo fdisk /dev/sdb
# 常用交互命令:
# m — 显示帮助(所有命令)
# p — 打印当前分区表
# n — 新建分区
# 选 p 主分区(primary)或 e 扩展分区(extended)
# 输入分区号(1-4)
# 输入起始扇区(直接回车使用默认)
# 输入大小:+20G(20G)、+500M(500MB)、直接回车(剩余全部)
# d — 删除分区
# t — 修改分区类型(8e=Linux LVM, 82=swap, 83=Linux)
# w — 写入分区表并退出(危险!操作不可撤销)
# q — 退出不保存
# 分区后通知内核刷新分区表
sudo partprobe /dev/sdb
# 查看分区表(不进入交互界面)
sudo fdisk -l /dev/sdb
parted — 支持 GPT,可脚本化
# 创建 GPT 分区表(大于 2TB 的磁盘必须用 GPT)
sudo parted /dev/sdb mklabel gpt
# 非交互式创建分区(适合脚本)
sudo parted /dev/sdb mkpart primary ext4 1MiB 21GiB # 1MiB 对齐起点(性能优化)
sudo parted /dev/sdb mkpart primary xfs 21GiB 100% # 剩余全部
# 查看分区信息
sudo parted /dev/sdb print
# 设置分区标志(如 LVM 标志)
sudo parted /dev/sdb set 1 lvm on
# gdisk — GPT 专用(类似 fdisk 的交互界面)
sudo gdisk /dev/sdb
8.3 文件系统:mkfs / tune2fs / xfs_info
# === mkfs — 格式化分区(创建文件系统)===
# ext4(最常见,兼容性最好)
sudo mkfs.ext4 /dev/sdb1
sudo mkfs.ext4 -L "data-disk" /dev/sdb1 # -L 设置卷标
sudo mkfs.ext4 -m 1 /dev/sdb1 # -m 保留空间比例(默认5%,数据盘设1%)
# XFS(高性能,大文件,RHEL/CentOS 默认)
sudo mkfs.xfs /dev/sdb2
sudo mkfs.xfs -L "fast-data" /dev/sdb2
# Btrfs(支持快照、压缩、RAID)
sudo mkfs.btrfs /dev/sdb3
sudo mkfs.btrfs -L "btrfs-pool" -d raid1 /dev/sdb3 /dev/sdc3 # RAID1
# FAT32(U盘,跨平台兼容)
sudo mkfs.fat -F32 /dev/sdb4
sudo mkfs.vfat /dev/sdb4
# === tune2fs — 调整 ext4 文件系统参数 ===
sudo tune2fs -l /dev/sda1 # 查看文件系统信息
sudo tune2fs -L "new-label" /dev/sda1 # 修改卷标
sudo tune2fs -m 1 /dev/sda1 # 减少保留块(节省空间)
sudo tune2fs -i 0 -c 0 /dev/sda1 # 禁用定期自动 fsck
# === xfs_info — 查看 XFS 文件系统信息 ===
sudo xfs_info /dev/sdb2
sudo xfs_info /mnt/data # 也可以指定挂载点
| 文件系统 | 优势 | 适用场景 | 最大文件/分区 |
|---|---|---|---|
| ext4 | 成熟稳定,兼容性最好,工具丰富 | 通用场景、系统分区 | 16TB / 1EB |
| XFS | 高并发写入,大文件性能优秀,在线扩容 | 数据库、媒体存储、高吞吐 | 8EB / 8EB |
| Btrfs | 快照、透明压缩、内置 RAID、校验和 | 桌面、容器存储、NAS | 16EB / 16EB |
| FAT32 | 跨平台(Windows/macOS/Linux) | U盘、UEFI 分区、嵌入式 | 4GB / 2TB |
8.4 挂载与 /etc/fstab
# === mount / umount ===
sudo mkdir -p /mnt/data
sudo mount /dev/sdb1 /mnt/data # 基本挂载
sudo mount -t xfs /dev/sdb2 /mnt/fast # 指定文件系统类型
sudo mount -o ro /dev/sdb1 /mnt/data # 只读挂载
sudo mount -o remount,rw /mnt/data # 重新挂载为读写
sudo mount -o noatime,nodiratime /dev/sdb1 /mnt/data # 禁用访问时间(性能优化)
# 查看已挂载的文件系统
mount | grep sdb
findmnt # 树状显示挂载信息
findmnt /mnt/data # 查看特定挂载点
# 卸载
sudo umount /mnt/data
sudo umount /dev/sdb1
sudo umount -l /mnt/data # -l 延迟卸载(busy 时)
# === /etc/fstab — 持久化挂载配置 ===
# 格式:设备 挂载点 文件系统类型 选项 dump pass
# dump: 0=不备份 1=备份(已基本弃用)
# pass: 0=不检查 1=根分区 2=其他分区(fsck 优先级)
# 推荐用 UUID 而非 /dev/sdb1(设备名可能因硬件变化而改变)
sudo blkid /dev/sdb1 # 获取 UUID
/etc/fstab 完整示例
# /etc/fstab — 文件系统挂载配置
#
# 根分区(系统盘,UUID 方式,ext4)
UUID=a1b2c3d4-1234-5678-abcd-ef0123456789 / ext4 errors=remount-ro 0 1
# Boot 分区
UUID=ABCD-EF01 /boot/efi vfat umask=0077 0 1
# 数据盘(XFS,禁用访问时间记录提升性能)
UUID=b2c3d4e5-2345-6789-bcde-f01234567890 /data xfs defaults,noatime 0 2
# Swap 分区
UUID=c3d4e5f6-3456-789a-cdef-012345678901 none swap sw 0 0
# NFS 远程挂载(网络文件系统)
192.168.1.100:/exports/shared /mnt/shared nfs defaults,_netdev 0 0
# _netdev 告诉系统等网络就绪后再挂载
# tmpfs(内存文件系统,重启清空,适合临时文件)
tmpfs /tmp tmpfs defaults,size=2G 0 0
# 测试 fstab 语法(不实际挂载,避免错误配置导致无法启动)
sudo mount -a --fake # 检查语法(某些发行版支持)
sudo mount -a # 挂载 fstab 中所有 auto 条目
8.5 LVM 逻辑卷管理
LVM(Logical Volume Manager)在物理磁盘和文件系统之间增加了一个抽象层,实现磁盘的灵活管理:无需停机扩容、跨多块磁盘合并为一个逻辑卷、快照备份等能力。生产服务器的数据盘几乎都应该使用 LVM。
LVM 三层架构(ASCII 图示)
# LVM 架构层次图:
#
# 文件系统层 ┌──────────────────────────────────┐
# │ /dev/vg_data/lv_app (ext4) │ 逻辑卷 (LV)
# │ /dev/vg_data/lv_db (xfs) │ Logical Volume
# └──────────────┬───────────────────┘
# │ 属于同一个卷组
# 卷组层 ┌──────────────▼───────────────────┐
# │ vg_data (VG) │ 卷组 (VG)
# │ 总容量 = PV1 + PV2 │ Volume Group
# └──────┬────────────────┬──────────┘
# │ │
# 物理卷层 ┌────────▼──┐ ┌────────▼──┐
# │ /dev/sdb │ │ /dev/sdc │ 物理卷 (PV)
# │ (500 GB) │ │ (500 GB) │ Physical Volume
# └───────────┘ └───────────┘
# ↑ ↑
# 物理磁盘/分区 物理磁盘/分区
PV / VG / LV 完整操作
# === 第一步:创建物理卷 (PV) ===
sudo pvcreate /dev/sdb /dev/sdc # 将磁盘初始化为 PV(可以是整块盘或分区)
sudo pvs # 简洁查看 PV
sudo pvdisplay /dev/sdb # 详细查看 PV 信息
# === 第二步:创建卷组 (VG) ===
sudo vgcreate vg_data /dev/sdb /dev/sdc # 创建名为 vg_data 的卷组,包含两块盘
sudo vgs # 简洁查看 VG
sudo vgdisplay vg_data # 详细查看 VG
# 向已有卷组添加新磁盘(扩展卷组)
sudo pvcreate /dev/sdd
sudo vgextend vg_data /dev/sdd
# === 第三步:创建逻辑卷 (LV) ===
sudo lvcreate -L 100G -n lv_app vg_data # 创建 100G 的 lv_app 逻辑卷
sudo lvcreate -L 200G -n lv_db vg_data # 创建 200G 的 lv_db 逻辑卷
sudo lvcreate -l 100%FREE -n lv_backup vg_data # 使用卷组全部剩余空间
sudo lvs # 简洁查看 LV
sudo lvdisplay /dev/vg_data/lv_app # 详细查看 LV
# 格式化并挂载
sudo mkfs.ext4 /dev/vg_data/lv_app
sudo mkfs.xfs /dev/vg_data/lv_db
sudo mkdir -p /app /db
sudo mount /dev/vg_data/lv_app /app
sudo mount /dev/vg_data/lv_db /db
# === LV 在线扩容(无需卸载!)===
# 1. 扩展逻辑卷大小
sudo lvextend -L +50G /dev/vg_data/lv_app # 增加 50G
sudo lvextend -L 200G /dev/vg_data/lv_app # 扩展到 200G(总大小)
sudo lvextend -l +100%FREE /dev/vg_data/lv_app # 使用 VG 中所有剩余空间
# 2. 扩展文件系统(ext4)
sudo resize2fs /dev/vg_data/lv_app # ext4 扩展(支持在线扩容)
# 2. 扩展文件系统(XFS,xfs 不支持缩小,只能扩大)
sudo xfs_growfs /db # XFS 用挂载点
# 一步完成(lvextend 带 -r 自动 resize 文件系统)
sudo lvextend -L +50G -r /dev/vg_data/lv_app
# === LV 快照(用于备份)===
sudo lvcreate -L 10G -s -n lv_app_snap /dev/vg_data/lv_app # 创建快照
sudo mount -o ro /dev/vg_data/lv_app_snap /mnt/snap # 只读挂载快照
sudo lvremove /dev/vg_data/lv_app_snap # 删除快照
8.6 fsck:文件系统检查与修复
# === 重要:fsck 必须在文件系统未挂载时运行!===
# ext4 文件系统检查
sudo umount /dev/sdb1
sudo e2fsck -f /dev/sdb1 # -f 强制检查(即使标记为 clean)
sudo e2fsck -f -y /dev/sdb1 # -y 自动回答 yes(非交互)
sudo e2fsck -f -n /dev/sdb1 # -n 只读检查,不修改(安全)
# 通用 fsck(自动选择后端)
sudo fsck /dev/sdb1
sudo fsck -t ext4 /dev/sdb1 # 指定文件系统类型
sudo fsck -a /dev/sdb1 # 自动修复(等同 -y)
# XFS 文件系统修复
sudo xfs_repair /dev/sdb2 # XFS 修复(挂载会失败,则卸载后运行)
sudo xfs_repair -n /dev/sdb2 # 只读检查
sudo xfs_repair -L /dev/sdb2 # -L 清空日志(最后手段,可能丢数据)
# 何时需要 fsck?
# 1. 系统崩溃或异常断电后
# 2. mount 时显示文件系统错误
# 3. /etc/fstab 中 pass 字段为 1 或 2 时,系统启动自动运行
# 4. 手动定期维护(tune2fs -c 设置检查间隔)
# 强制下次启动时对根分区进行 fsck
sudo touch /forcefsck # 某些发行版
sudo tune2fs -C 1 /dev/sda1 # 将挂载计数设为 1(触发检查)
根分区如何 fsck? 根分区(
/)正在运行时无法卸载,必须在单用户模式或从 Live CD/USB 启动后操作。进入单用户模式:重启时在 GRUB 界面按e编辑启动项,在linux行末尾追加single或init=/bin/bash,然后Ctrl+X启动。
8.7 dd:磁盘克隆与镜像
dd(disk duplicator)是 Linux 中的底层数据复制工具,直接操作字节流,可用于磁盘克隆、创建 ISO 镜像、测试磁盘速度、安全擦除数据。使用时须格外小心:if(输入)和 of(输出)如果写反,会把数据盘清空。
# === 基本语法 ===
# dd if=输入文件 of=输出文件 bs=块大小 count=块数
# === 磁盘克隆(整盘复制)===
sudo dd if=/dev/sda of=/dev/sdb bs=4M status=progress # 克隆 sda 到 sdb(大小必须相同或更大)
# status=progress:显示进度(Linux 4.x+ 支持)
# === 创建磁盘镜像文件 ===
sudo dd if=/dev/sda of=/backup/sda.img bs=4M status=progress
# 压缩备份(节省存储空间)
sudo dd if=/dev/sda bs=4M | gzip -c > /backup/sda.img.gz
# 使用 pigz 并行压缩(更快)
sudo dd if=/dev/sda bs=4M | pigz > /backup/sda.img.gz
# === 恢复镜像到磁盘 ===
sudo dd if=/backup/sda.img of=/dev/sdb bs=4M status=progress
gunzip -c /backup/sda.img.gz | sudo dd of=/dev/sdb bs=4M status=progress
# === 写入 ISO 到 U 盘 ===
sudo dd if=ubuntu-22.04.iso of=/dev/sdc bs=4M status=progress conv=fdatasync
# conv=fdatasync 确保所有数据写入完成再退出(避免拔出时数据丢失)
# === 测试磁盘写入速度 ===
dd if=/dev/zero of=/tmp/test bs=1G count=1 oflag=direct
# oflag=direct 绕过缓存,测试真实写入速度
# === 测试磁盘读取速度 ===
dd if=/dev/sda of=/dev/null bs=4M count=1000 status=progress
# === 安全擦除磁盘(写入随机数据)===
sudo dd if=/dev/urandom of=/dev/sdb bs=4M status=progress
# 注意:大磁盘耗时极长,SSD 建议用 hdparm --security-erase
# === 只备份分区而非整盘 ===
sudo dd if=/dev/sda1 of=/backup/boot.img bs=4M status=progress
8.8 smartctl:磁盘健康预测
# 安装
sudo apt install smartmontools
# === 基本健康检查 ===
sudo smartctl -H /dev/sda # 快速健康状态(PASSED/FAILED)
sudo smartctl -a /dev/sda # 完整 SMART 属性报告
sudo smartctl -i /dev/sda # 磁盘基本信息
# === 运行自检 ===
sudo smartctl -t short /dev/sda # 短测试(1-2分钟,后台运行)
sudo smartctl -t long /dev/sda # 长测试(数小时,全盘扫描)
sudo smartctl -t conveyance /dev/sda # 运输测试(模拟运输损坏)
# 查看测试结果
sudo smartctl -l selftest /dev/sda
# === 关键 SMART 属性解读 ===
# Reallocated_Sector_Ct (ID 5) — 重映射扇区数。非0即硬盘有坏扇区,越多越危险
# Spin_Retry_Count (ID 10) — 主轴启动重试次数。非0说明机械部件可能有问题
# UDMA_CRC_Error_Count (ID 199)— 接口传输错误。非0可能是数据线问题
# Current_Pending_Sector (ID 197)— 待重映射扇区(不稳定扇区)。非0紧急关注
# Offline_Uncorrectable (ID 198)— 无法纠错的扇区。非0极度危险,立即备份!
# Power_On_Hours (ID 9) — 通电总小时数。判断磁盘寿命
# Temperature_Celsius (ID 194)— 磁盘温度。超过 55°C 需要关注
# NVMe SSD 健康检查
sudo smartctl -a /dev/nvme0n1
# 启用自动监控(smartd 守护进程)
sudo systemctl enable smartd
sudo systemctl start smartd
# 配置文件:/etc/smartd.conf
8.9 软件 RAID:mdadm 简介
| RAID 级别 | 最少磁盘 | 容量利用率 | 可容忍故障 | 读写性能 | 适用场景 |
|---|---|---|---|---|---|
| RAID 0 | 2 | 100% | 无(任一盘坏即全损) | 读写均最快 | 临时数据、缓存 |
| RAID 1 | 2 | 50% | 1块盘 | 读提升,写与单盘同 | 系统盘、高可靠性 |
| RAID 5 | 3 | (N-1)/N | 1块盘 | 读快,写有奇偶计算开销 | 平衡容量与可靠性 |
| RAID 6 | 4 | (N-2)/N | 2块盘 | 读快,写开销更高 | 大容量存储,高可靠 |
| RAID 10 | 4 | 50% | 每镜像组1块盘 | 读写均快(RAID 0+1) | 数据库、高 IOPS |
# 安装 mdadm
sudo apt install mdadm
# 创建 RAID 1(镜像,两块盘)
sudo mdadm --create /dev/md0 --level=1 --raid-devices=2 /dev/sdb /dev/sdc
# 创建 RAID 5(三块盘)
sudo mdadm --create /dev/md0 --level=5 --raid-devices=3 /dev/sdb /dev/sdc /dev/sdd
# 查看 RAID 状态
cat /proc/mdstat
sudo mdadm --detail /dev/md0
# 保存 RAID 配置
sudo mdadm --detail --scan >> /etc/mdadm/mdadm.conf
# 格式化并挂载 RAID 设备(与普通磁盘相同)
sudo mkfs.ext4 /dev/md0
sudo mount /dev/md0 /mnt/raid
8.10 磁盘性能分析
# === hdparm — 简单速度测试 ===
sudo hdparm -t /dev/sda # 缓冲读测试(排除 OS 缓存)
sudo hdparm -T /dev/sda # 纯缓存读测试
# === iostat — I/O 统计(sysstat 包)===
sudo apt install sysstat
iostat # 基本 I/O 统计
iostat -dx 2 # -d 磁盘,-x 扩展信息,每2秒刷新
iostat -dx /dev/sda 2 # 只看 sda
# 关键指标解读:
# %util — 设备繁忙率(接近100%说明磁盘成为瓶颈)
# await — 平均 I/O 等待时间(ms,机械盘正常 **章节总结:** 本章覆盖了 Linux 存储管理的完整技术栈:从 `lsblk/blkid` 了解磁盘全景,到 `fdisk/parted` 精确分区,`mkfs` 选择合适的文件系统,`fstab` 配置持久挂载,LVM 实现灵活的在线扩容,`fsck/e2fsck` 紧急修复,`dd` 克隆备份,`smartctl` 预测故障,以及 RAID 提供冗余保护。这些技能构成了服务器存储运维的核心能力。下一章将进入 Shell 脚本编程:变量与控制流。
上一章
← 第7章:网络工具全解
下一章
第9章:变量与控制流 →