前言:为什么你必须学会磁盘管理
你有没有遇到过这种情况——VPS 跑着跑着突然服务挂了,一查才发现 /var 分区满了?MySQL 写不进去数据、Nginx 报 500、Docker 容器莫名其妙退出……根因都是磁盘满了。
我刚用 VPS 那会儿就踩过这个坑。WordPress 站点突然打不开,SSH 上去 df -h 一看,/ 分区使用率 100%。当时满脑子「怎么办怎么办」,最后只能删日志、清缓存临时续命。后来升级了 VPS 磁盘,发现新加的磁盘在系统里根本看不到——因为没分区、没格式化、没挂载。
这就是今天这篇文章要解决的问题。我会从头讲 Linux 磁盘管理的完整链路:查看磁盘 → 分区 → 格式化 → 挂载 → 永久挂载,以及进阶的 LVM 逻辑卷管理 + 在线扩容。读完你会发现这玩意儿没想象中那么可怕。
本文基于 Ubuntu 24.04 LTS,大部分命令在 Debian/CentOS/RHEL 上通用,差异处会单独标注。
第一步:查看磁盘信息 — 先搞清楚你有多少盘
在动手之前,先摸清家底。三个命令搞定:
1. lsblk — 最直观的磁盘树状图
$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sda 8:0 0 50G 0 disk
├─sda1 8:1 0 49G 0 part /
├─sda14 8:14 0 4M 0 part
└─sda15 8:15 0 106M 0 part /boot/efi
sdb 8:16 0 100G 0 disk
sda 是系统盘(已分区),sdb 是刚加的数据盘——100G,赤裸裸一整块,没有分区。这就是我们要操作的对象。
2. fdisk -l — 传统分区表查看
$ sudo fdisk -l /dev/sdb
Disk /dev/sdb: 100 GiB, 107374182400 bytes, 209715200 sectors
Disk model: QEMU HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
确认 /dev/sdb 没有分区表,可以放心操作。
3. df -h — 查看已挂载分区的使用情况
$ df -h
Filesystem Size Used Avail Use% Mounted on
/dev/sda1 49G 38G 8.6G 82% /
tmpfs 1.9G 1.1M 1.9G 1% /dev/shm
82% 的使用率还算安全,但如果超过 90% 就该警惕了。
第二步:传统分区 — fdisk 分区 + 格式化 + 挂载
如果不打算用 LVM(后面会讲),这条链路就是最标准的操作流程。以 /dev/sdb 这个 100G 空盘为例。
2.1 创建分区
$ sudo fdisk /dev/sdb
Welcome to fdisk (util-linux 2.39.3).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n # 新建分区
Partition type: p (primary) # 主分区
Partition number: 1
First sector: 2048 # 默认
Last sector: +100G # 或用回车使用全部空间
Command (m for help): w # 写入并退出
The partition table has been altered.
Syncing disks.
再跑一次 lsblk,你会看到 sdb1 出现了。
$ lsblk /dev/sdb
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb 8:16 0 100G 0 disk
└─sdb1 8:17 0 100G 0 part
2.2 格式化 — 创建文件系统
分区只是划了块地,文件系统才是决定「怎么存」的。Ubuntu 上首选 ext4:
$ sudo mkfs.ext4 /dev/sdb1
mke2fs 1.47.0 (5-Feb-2023)
Creating filesystem with 26214400 4k blocks and 6553600 inodes
Filesystem UUID: a1b2c3d4-e5f6-7890-abcd-ef1234567890
Superblock backups stored on blocks:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208,
4096000, 7962624, 11239424, 20480000, 23887872
Allocating group tables: done
Writing inode tables: done
Creating journal (131072 blocks): done
Writing superblocks and filesystem accounting information: done
格式选择建议:
- ext4:最通用,稳定可靠,单文件最大 16TB
- XFS:CentOS/RHEL 默认,大文件性能好,但不支持缩容
- btrfs:支持快照和压缩,适合折腾党
2.3 挂载 — 让系统能访问
$ sudo mkdir -p /data
$ sudo mount /dev/sdb1 /data
$ df -h /data
Filesystem Size Used Avail Use% Mounted on
/dev/sdb1 98G 24K 93G 1% /data
挂载成功。但有个问题:重启后这个挂载就没了。因为 mount 命令只是临时的。
2.4 永久挂载 — 写入 /etc/fstab
/etc/fstab 是系统启动时自动挂载的配置文件。这一步操作不当会导致系统无法启动,务必小心。
先用 blkid 获取分区的 UUID(推荐用 UUID 而非设备名,因为设备名可能变化):
$ sudo blkid /dev/sdb1
/dev/sdb1: UUID="a1b2c3d4-e5f6-7890-abcd-ef1234567890" TYPE="ext4"
在 /etc/fstab 末尾追加一行:
$ echo 'UUID=a1b2c3d4-e5f6-7890-abcd-ef1234567890 /data ext4 defaults 0 2' | sudo tee -a /etc/fstab
验证 fstab 是否写对(不会真的挂载,只做语法检查):
$ sudo mount -a
# 没有报错 = 没问题
重启后 df -h 确认 /data 还在,就大功告成了。
第三步:LVM 逻辑卷管理 — 弹性伸缩的王牌
传统分区有个致命缺点:一旦分好就不能在线扩容。比如你把 /var 分了 20G,半年后满了,要么迁移数据,要么停机重分区——都是一身汗。
LVM(Logical Volume Manager)就是来解决这个问题的。它在你和物理磁盘之间加了一个抽象层,让你可以随时加减空间。
LVM 三层架构
先理解这三个概念,后面的操作就顺了:
- PV(Physical Volume,物理卷):你的真实磁盘或分区,比如
/dev/sdb1 - VG(Volume Group,卷组):把多个 PV 合并成一个大池子
- LV(Logical Volume,逻辑卷):从 VG 池子里切出来的「虚拟分区」
打个比方:你有三块 100G 的硬盘(PV),把它们扔进一个 300G 的大池子(VG),然后从中切出 80G 给根目录、120G 给 home、16G 给 swap(三个 LV)。哪天根目录不够了,从池子里再划 20G 过来,在线扩容,服务不停。
3.1 创建 PV
$ sudo pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created.
$ sudo pvs
PV VG Fmt Attr PSize PFree
/dev/sdb lvm2 --- 100.00g 100.00g
3.2 创建 VG
$ sudo vgcreate vg_data /dev/sdb
Volume group "vg_data" successfully created
$ sudo vgs
VG #PV #LV #SN Attr VSize VFree
vg_data 1 0 0 wz--n- 100.00g 100.00g
3.3 创建 LV
从 vg_data 中切出 30G 作为数据存储卷:
$ sudo lvcreate -n lv_data -L 30G vg_data
Logical volume "lv_data" created.
$ sudo lvs
LV VG Attr LSize Pool Origin Data% Meta%
lv_data vg_data -wi-a----- 30.00g
3.4 格式化 + 挂载 LV
$ sudo mkfs.ext4 /dev/vg_data/lv_data
$ sudo mkdir -p /mnt/data
$ sudo mount /dev/vg_data/lv_data /mnt/data
$ df -h /mnt/data
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data 30G 24K 28G 1% /mnt/data
永久挂载同理,加到 /etc/fstab:
UUID=$(sudo blkid -s UUID -o value /dev/vg_data/lv_data)
echo "UUID=$UUID /mnt/data ext4 defaults 0 2" | sudo tee -a /etc/fstab
第四步:LVM 在线扩容 — 不停机加空间
这才是 LVM 的真正价值。假设 lv_data 的 30G 快满了,VG 池子里还有 70G 空闲。
4.1 扩展 LV
$ sudo lvextend -L +20G /dev/vg_data/lv_data
Size of logical volume vg_data/lv_data changed from 30.00 GiB to 50.00 GiB.
Logical volume vg_data/lv_data successfully resized.
4.2 扩展文件系统(ext4)
LV 扩容了,但文件系统还不知道。用 resize2fs(ext4 专用)让它识别新空间:
$ sudo resize2fs /dev/vg_data/lv_data
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/vg_data/lv_data is mounted on /mnt/data; on-line resizing required
old_desc_blocks = 4, new_desc_blocks = 7
The filesystem on /dev/vg_data/lv_data is now 13107200 (4k) blocks long.
验证一下:
$ df -h /mnt/data
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/vg_data-lv_data 50G 24K 47G 1% /mnt/data
30G → 50G,在线完成,服务没中断。注意 XFS 文件系统用 xfs_growfs 而不是 resize2fs。
4.3 如果要缩减空间呢?
ext4 支持缩容,但必须先卸载:
$ sudo umount /mnt/data
$ sudo e2fsck -f /dev/vg_data/lv_data # 先检查文件系统
$ sudo resize2fs /dev/vg_data/lv_data 20G # 缩小文件系统到 20G
$ sudo lvreduce -L 20G /dev/vg_data/lv_data # 缩小 LV
$ sudo mount /dev/vg_data/lv_data /mnt/data
缩容有风险,生产环境建议直接加盘而不是缩容——磁盘很便宜,数据丢了哭都来不及。
第五步:实战场景 — VPS 根分区满了怎么办
这是最常遇到的问题。以 Ubuntu 24.04 VPS 为例,根分区 / 满了的排查和解决流程:
5.1 定位大文件
$ sudo du -h --max-depth=1 / 2>/dev/null | sort -hr | head -10
32G /var
18G /usr
4.2G /home
2.1G /opt
1.5G /tmp
...
/var 占了 32G,进一步排查:
$ sudo du -h --max-depth=1 /var 2>/dev/null | sort -hr | head -5
28G /var/log
2.5G /var/lib
...
/var/log 是罪魁祸首——通常是被 Docker 或 Nginx 日志撑爆的。
5.2 清理日志(治标)
$ sudo journalctl --vacuum-size=500M # systemd 日志限制 500M
$ sudo find /var/log -type f -name "*.log" -mtime +30 -delete # 删 30 天前的日志
$ sudo docker system prune -a --volumes # 清理 Docker 垃圾(谨慎!)
5.3 配置日志轮转(治本)
在 /etc/logrotate.d/ 下创建配置文件,让系统自动压缩和删除旧日志:
$ cat /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 640 root adm
}
5.4 如果还不够 — 扩容 VPS 磁盘
云厂商后台扩容磁盘后,还需要在系统里让分区识别新空间。如果用的是 LVM:
$ sudo pvresize /dev/sda3 # 让 PV 识别扩容后的磁盘
$ sudo lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv # LV 吃掉所有剩余空间
$ sudo resize2fs /dev/ubuntu-vg/ubuntu-lv # 扩展文件系统
如果不是 LVM(传统分区),就需要更麻烦的操作——这恰恰说明为什么建议生产环境用 LVM。
第六步:常用命令速查表
| 操作 | 命令 |
|---|---|
| 查看磁盘 | lsblk, fdisk -l, df -h |
| 分区 | fdisk /dev/sdX |
| 格式化 ext4 | mkfs.ext4 /dev/sdX1 |
| 挂载 | mount /dev/sdX1 /path |
| 永久挂载 | 编辑 /etc/fstab,用 UUID |
| 创建 PV | pvcreate /dev/sdX |
| 创建 VG | vgcreate vg_name /dev/sdX |
| 创建 LV | lvcreate -n lv_name -L 10G vg_name |
| 扩容 LV | lvextend -L +5G /dev/vg/lv |
| 扩容文件系统 | resize2fs (ext4) / xfs_growfs (XFS) |
常见问题(FAQ)
Q: 挂载时报错 “wrong fs type, bad option, bad superblock” 怎么办?
最常见的原因是该分区还没有格式化。先确认分区存在(lsblk),然后用 sudo mkfs.ext4 /dev/sdX1 格式化后再挂载。如果已经格式化过,检查文件系统是否损坏:sudo fsck /dev/sdX1。
Q: LVM 和传统分区到底该怎么选?
推荐用 LVM,除非是极简场景(比如只有一个 20G 的小 VPS)。原因很简单:磁盘需求是动态增长的,你今天觉得 50G 够用,三个月后可能就需要 200G。LVM 让你在线扩容而不停机。Ubuntu Server 安装时默认就会使用 LVM,说明官方也推荐这个方案。唯一不推荐 LVM 的场景是嵌入式设备或极致性能要求的环境(多一层抽象有极轻微的性能开销)。
Q: /etc/fstab 写错了导致系统无法启动怎么办?
进入恢复模式(GRUB 菜单选 “Advanced options → recovery mode”),选 “Drop to root shell prompt”,然后:
1. mount -o remount,rw / 让根分区可写
2. nano /etc/fstab 修改或注释掉错误行
3. reboot 重启。
如果你用的是云 VPS(AWS/阿里云/腾讯云等),可以通过控制台的 VNC 或救援模式进入系统。所以改 fstab 前一定先跑 mount -a 验证。
总结
Linux 磁盘管理的核心就两条链路:
传统路线: fdisk 分区 → mkfs 格式化 → mount 挂载 → /etc/fstab 永久化
LVM 路线: pvcreate → vgcreate → lvcreate → mkfs → mount → lvextend + resize2fs 在线扩容
我个人现在所有 VPS 都用 LVM——曾经半夜两点被 /var 爆满搞过一次之后,就再也不想经历第二次了。花 10 分钟把 LVM 配好,换来的是随时在线扩容的安全感,值。
如果你刚接触 VPS,建议先在虚拟机里练一遍这些命令,搞坏了大不了快照回滚。等你用熟了,这些操作会像 ls 和 cd 一样自然。
推荐阅读:
- Linux crontab 定时任务完全指南 — 用 cron 定期清理磁盘
- VPS 安全加固完整指南 — 配置好磁盘后别忘了安全
- Let’s Encrypt SSL 证书自动续期 — HTTPS 配置一站搞定