Linux磁盘扩容实战:从挂载新盘到LVM在线扩容
2026/9/18 2:37:50 网站建设 项目流程

后台经常会收到这类提问:“服务器根目录满了怎么办?”“某个数据目录容量不够,能不能加一块盘直接顶上?”这类问题在Linux运维里实在太常见了。很多刚接触Linux的朋友一看到df -h/的使用率冲到100%就开始慌,以为只能重装系统或者删库跑路。其实不用这么紧张,Linux的目录挂载机制本身就是为这种场景设计的:你可以随时加一块新磁盘,把它挂载到根目录或者某个指定目录上,让那个目录直接使用新盘的空间,应用路径完全不用改。这篇文章就是我整理的一份完整实操记录,围绕“挂载磁盘扩容”这个主题,把从磁盘诊断、分区格式化、临时/永久挂载,到根目录替换和LVM在线扩容的整套流程都过一遍,配合我实际踩过的坑,希望能给同样被磁盘空间卡住的朋友一条清晰的解决路径。

1. 扩容前的诊断:目录是真的不够,还是垃圾文件太多

1.1 三个命令快速定位磁盘现状

遇到磁盘告警,我会先做三件事,基本上三分钟就能判断出问题的大致范围。

第一个是df -h,看整体使用率。重点关注//var/home这类大型目录所在分区的使用百分比。如果某个分区达到90%以上,基本可以判断目前确实处于空间紧张状态。

第二个是lsblk,看系统里有没有“新盘未挂载”的情况。很多云服务器或者虚拟机加盘之后并不会自动挂载,盘已经在系统里了,只是还没被使用。lsblk输出里如果看到一个没有挂载点的磁盘(比如/dev/sdb/dev/vdb),那说明系统里其实有可用资源,只是还没有纳入文件系统管理。

第三个是du,找出到底是哪个目录在疯狂吃空间。我会用这条命令快速定位:

du -h --max-depth=1 / 2>/dev/null | sort -hr | head -20

这条命令会把根目录下各个一级子目录按占用空间从大到小排列。运行完你通常能看到两种结果:一种是某个业务目录(比如/data/var/lib/mysql/www)特别大,另一种是/usr或者/var这类系统目录异常膨胀。两种情况对应的扩容策略是完全不同的,先定位再动手,能少走很多弯路。

1.2 先清理再扩容,避免“一满就加盘”的冲动

说句实在话,我处理过的磁盘告警里,至少有三分之一靠清理就能解决,根本不需要动到磁盘挂载这种层面。常见的大户有这么几类:

systemd 日志。很多服务器默认的 journal 日志积累起来非常惊人,一条命令就能限制体积:

journalctl --vacuum-size=200M

这条命令会把 journal 日志压缩/清理到 200MB 以内。如果是长期运行的服务器,建议再加一条永久限制,修改/etc/systemd/journald.conf里的SystemMaxUse=200M,防止日志再次膨胀。

Docker 相关的资源。如果机器上用 Docker,/var/lib/docker很容易吃满磁盘。容器日志、悬空镜像、构建缓存都会堆积。可以先看docker system df,然后用docker system prune清理悬空资源,并限制容器日志大小。比如在/etc/docker/daemon.json里加上:

{ "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } }

包管理器缓存。yum 或 apt 的缓存文件也会占掉好几个G。分别用yum clean allapt-get clean清掉,安安静静地就腾出空间了。

临时文件和旧的压缩包。很多人把下载的安装包、备份包直接扔在/tmp或者/root下,时间一长非常占地方。find / -xdev -size +500M -exec ls -lh {} \;这条命令能快速找出超过500MB的大文件,看看有哪些是可以删掉的。

这里要提醒一句:清理要有度。数据库文件、业务日志、用户上传数据这些属于业务数据,别轻易删。我们要清理的是“确定无用”的系统垃圾。如果清理完空间依然吃紧,或者你明确知道某个目录会因为业务增长持续膨胀,那才进入下一步:挂载新盘。

2. 理解挂载机制:为什么目录空间不够,加一块盘就能解决

2.1 挂载的本质:目录只是文件系统树上的一个接入点

想理解“挂载磁盘扩容”这件事,必须先理解Linux里“一切皆文件”的底层设计。在Linux的视角里,磁盘不是一个一个的盘符,而是一个统一的目录树。一块物理磁盘要被使用,需要经过“分区 - 格式化 - 挂载”三个步骤,而“挂载”这个动作,本质上就是把一个设备上的文件系统“接入”到目录树的某个节点上。

这个节点就是挂载点。挂载点本身只是一个普通的目录,可以是空目录,也可以是已经有数据的目录。一旦某个分区被挂载到目录/data上,所有写入/data的数据就都会落到这个分区的存储空间里。目录本身不占固定的磁盘空间,真正的空间量取决于挂载在这个目录上的分区有多大。

用一句通俗的话来类比:分区相当于一个仓库,目录相当于门牌号。挂载就是把仓库和门牌号绑定在一起。当/data这个门牌号背后的仓库满了,你不需要把仓库里的东西都搬出来,只需要把一个新的、更大的仓库挂到同一个门牌号下,这个门牌号背后的可用空间就变大了。这就是挂载扩容最核心的逻辑。

2.2 三种扩容路径的取舍

针对“某个目录空间不足”的场景,实际操作中通常有三条路径:

  • 直接将新盘挂载到一个空目录。适合新增业务、新开一个存储目录,操作最简单,不需要动任何旧数据。
  • 将新盘挂载到已有数据的目录,需要先把旧数据迁移到新盘,再完成挂载替换。适合/data/www这类已有大量业务数据的目录。
  • 通过LVM逻辑卷在线扩容。如果系统安装时采用了LVM方案,根分区和部分大目录本身就是逻辑卷,可以做到几乎不中断服务就完成在线扩容,这种方式最优雅。

这三条路径的使用场景差异很大,我整理了一张对比表:

方案适用场景是否需要停机操作复杂度数据安全性
新盘挂载到空目录新增目录、新业务存储不需要无旧数据风险
新盘挂载到已有数据的目录业务目录空间不足需要短暂停写中等迁移数据时有风险
LVM在线扩容根目录、系统盘扩容基本不需要中高相对安全

选定方案之后,就可以动手实操了。下面两章我会分别演示“挂载到指定目录”和“挂载根目录/系统盘扩容”的完整流程。

3. 实操一:把新盘挂载到指定目录,给业务目录扩容

3.1 识别新磁盘并完成分区初始化

假设你要给/data目录扩容,这块目录目前挂在旧分区上,空间见底。你现在插入了一块新盘(在物理机上是新硬盘,在虚拟机上就是新增一块虚拟磁盘)。第一步是让系统识别到它。

lsblk

执行后能看到类似这样的输出:

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 100G 0 disk ├─sda1 8:1 0 1G 0 part /boot └─sda2 8:2 0 99G 0 part / sdb 8:16 0 200G 0 disk

sdb就是新加的磁盘,容量200G,目前没有任何分区和挂载点。接下来的操作要十分小心:确认目标磁盘是/dev/sdb,千万不要搞错盘符把系统盘给格式化了。在虚拟机上通常新盘是/dev/vdb或者/dev/sdb;在物理机上可以用lsscsilsblk -d -o name,size,model进一步确认。

然后对/dev/sdb进行分区:

fdisk /dev/sdb

进入交互界面后,依次输入:

n # 新建分区 p # 主分区 1 # 分区编号 回车 # 起始扇区默认 回车 # 结束扇区默认,使用整块盘 w # 保存并退出

完成后用lsblk查看,应该能看到sdb1这个分区了。这里解释一下为什么要分区:分区本质上是给整块盘建立一层“索引”,以后你可以基于这个分区做格式化、扩容、备份等操作;如果整块盘直接格式化也不报错,但后续管理会很不方便。对于超过2TB的大容量磁盘,fdisk默认的MBR分区表支持不了,需要用parted工具创建GPT分区表:

parted /dev/sdb mklabel gpt mkpart primary 0% 100% quit

分区做完之后就是格式化。Linux原生的文件系统通常选ext4xfs。我个人偏好ext4,原因是它成熟、稳定、兼容性好,而且支持在线扩容命令resize2fs。如果存储的是超大文件、高吞吐场景,xfs更合适。格式化命令:

mkfs.ext4 /dev/sdb1

执行后系统会输出文件系统相关的信息,这一步会把新分区变成Linux可以识别的文件系统。

3.2 临时挂载并迁移旧数据

新盘格式化之后,目前还是一张“空表”。如果/data目录里已经有业务数据,不能直接把新盘挂载到/data上,否则旧数据会被“隐藏”起来。正确流程是先临时挂载到别的目录,把旧数据完整复制过去,再完成挂载替换。

先把新分区临时挂载到/mnt/data_new

mkdir -p /mnt/data_new mount /dev/sdb1 /mnt/data_new

然后同步旧数据。推荐用rsync,它比cp快,而且支持断点续传、实时显示进度,更适合大批量数据迁移:

rsync -avzh --info=progress2 /data/ /mnt/data_new/

注意命令里的斜杠位置:/data/结尾带斜杠表示复制目录里的所有内容,而不是把data这个目录本身嵌套进去;目标/mnt/data_new/同样带斜杠,表示直接放在该目录下。如果路径不带斜杠,复制出来就会变成/mnt/data_new/data/...,导致目录层级错乱。

迁移数据这个环节,最怕的是业务还在不停写入。如果条件允许,最好先停掉对应业务,或者至少保持数据不会写入的状态。如果实在不能停业务,建议先做一次rsync同步,然后短暂停服几秒钟,再做一次增量同步:

rsync -avzh --delete /data/ /mnt/data_new/

加了--delete参数后,会把源目录已经删除的文件同步删除掉,保证目标目录和源目录完全一致。数据同步完,在卸载旧目录之前,最好做一次对比验证:

du -sh /data/ /mnt/data_new/

两边容量一致,基本可以放心进入下一步。

3.3 永久挂载:用UUID写入fstab

数据同步完,把临时挂载的新分区卸载,然后正式挂载到/data

umount /mnt/data_new mount /dev/sdb1 /data

此时再执行df -h /data,应该能看到/data已经使用新分区的空间了,原来的数据也都还在(通过刚才的rsync复制过来的)。不过到这里只完成了一半,重启之后挂载关系会失效,还需要把它写进/etc/fstab实现开机自动挂载。

先获取新分区的UUID:

blkid /dev/sdb1

输出里会有一串类似UUID="a1b2c3d4-..."的字符串。接下来编辑/etc/fstab,在文件末尾加一行:

UUID=a1b2c3d4-... /data ext4 defaults 0 2

这行配置有6个字段,我先解释清楚:第一个字段是设备标识,这里用UUID,比直接写/dev/sdb1更可靠;第二个是挂载点/data;第三个是文件系统类型ext4;第四个defaults是挂载选项,包含rw、suid、dev、exec、auto、nouser、async等默认参数;第五个0表示dump备份标记,一般填0;第六个2表示开机时文件系统检查顺序,根分区填1,其他挂载点填2,填0表示不检查。

改完/etc/fstab后,千万别急着重启,先跑一条测试命令:

mount -a

这条命令会按照/etc/fstab重新挂载所有尚未挂载的条目。如果配置有误,它会直接报错,你可以当场修改。如果没报错,再用df -h /data确认挂载正常,此时重启也不会出问题。

3.4 挂载后的验证与权限处理

挂载替换完成不代表万事大吉,还有几个细节等着处理。

一个是权限。新格式化的分区挂载后,目录所有者默认是root。如果/data原来属于某个业务账号(比如wwwmysql),业务可能读取不了文件。需要用chown修正:

chown -R www:www /data

另一个是测试写入。在业务正式恢复前,手动创建和删除一个测试文件,确认读写正常:

touch /data/.test && rm /data/.test

如果这两个命令都顺利执行,说明挂载目录可写、可删,没有权限问题。最后重启一次服务器验证整个流程没有遗漏,开机后df -h /data依然显示新分区的容量,这次扩容就算真正完成了。

4. 实操二:挂载新盘替换根目录,给系统盘扩容

4.1 为什么根目录不能在线直接替换

比“指定目录扩容”更棘手的场景是根目录本身满了。很多人会想:既然普通目录可以挂载新盘替换,那根目录/是不是也能直接卸载再挂新盘?答案是不行。根目录是整棵目录树的地基,内核、systemd、各种服务进程无时无刻不在读写它。你一旦尝试umount /,系统会直接卡死甚至内核崩溃,这在生产环境是不可接受的。

所以根目录扩容的现实路径只有两条:要么在系统运行期间,通过LVM逻辑卷在线扩展根分区所在的空间;要么借助外部介质(比如救援模式、U盘启动盘)把根文件系统整体迁移到新的大容量磁盘上,再用新盘作为系统盘启动。前者是把空间“扩”出来,后者是把系统“挪”过去。

4.2 方法一:整盘迁移法替换根目录

整盘迁移法适用于“系统盘整体太小,想换一块更大的盘”的场景,比如虚拟机原盘20G爆满,想换成100G的新盘。这个操作步骤比较多,我在这里给出完整流程,但务必强调:一定要在虚拟机或测试环境先演练,生产环境请先做整机备份。

准备阶段。新盘(假设/dev/sdb)先完成分区和格式化,方法和上一章一样。然后把新盘挂载到临时目录:

mkdir -p /mnt/newroot mount /dev/sdb1 /mnt/newroot

同步根文件系统。执行rsync,把当前根目录的所有内容复制到新盘的挂载点,同时要排除掉那些运行时虚拟目录:

rsync -axHAWXS --numeric-ids --info=progress2 \ --exclude={"/proc/*","/sys/*","/dev/*","/run/*","/tmp/*","/mnt/*","/media/*","/lost+found"} \ / /mnt/newroot/

命令里的-a是归档模式,-x表示不跨越文件系统边界,避免复制到其他挂载点,-H保留硬链接,-A保留ACL权限,-W整文件复制,-X保留扩展属性,-S稀疏文件优化。这些参数组合在一起,能最大程度保证复制出来的系统文件属性与原系统一致。--numeric-ids保证用户和组的ID不变,避免迁移后文件所有者错乱。

安装引导并修改fstab。同步完成后,需要进入新系统的环境,把引导程序安装到新盘上:

mount --bind /dev /mnt/newroot/dev mount --bind /proc /mnt/newroot/proc mount --bind /sys /mnt/newroot/sys chroot /mnt/newroot

进入chroot环境后,首先执行:

grub-install /dev/sdb update-grub

同时要编辑新盘上的/etc/fstab,把根分区的UUID改成新盘的UUID,否则重启后会找不到根文件系统。用blkid /dev/sdb1获取新UUID,然后修改/mnt/newroot/etc/fstab里根目录那一行。退出chroot,卸载所有绑定的目录,最后重启,并在BIOS/虚拟机启动菜单里选择从新盘启动。

这个流程操作起来很容易出错,一旦grub-install没跑成功或者fstab写错,新系统大概率起不来。所以我个人的建议是:如果只是想解决根目录空间不足,整盘迁移不是首选;优先考虑LVM方案,或者把/var/home这类消耗大户单独挂载到新盘上,变相给根目录减压。

4.3 方法二:LVM在线扩容,根目录扩容的优雅解法

LVM(Logical Volume Manager)是Linux里一套逻辑卷管理机制,它把物理磁盘、分区和文件系统的关系从“一对一”解耦成“物理卷 - 卷组 - 逻辑卷”三层结构。理解起来可以这样类比:物理卷PV相当于一块块砖头,卷组VG相当于把这些砖头砌成的一个大水池,逻辑卷LV相当于从水池里接出来的一根水管。当你觉得根目录这根水管出水不够时,只需要往水池里添加新砖头(新磁盘),然后把这部分容量划给根目录对应的水管就行,整个过程不需要断水,也就是不需要卸载根目录、不需要停机。

现在越来越多的发行版在安装系统时就默认使用LVM布局。可以用lsblk查看,如果发现类似/dev/mapper/centos-root/dev/mapper/ubuntu--vg-ubuntu--lv这样的名称,说明你的根分区就是逻辑卷,可以直接走LVM扩容。

需要扩容时,先创建物理卷:

pvcreate /dev/sdb1

然后把新物理卷加入现有的卷组。卷组名称可以通过vgs查看,假设叫centos(有些系统叫vg0ubuntu-vg):

vgextend centos /dev/sdb1

此时水池的容量已经扩大,接下来把新增容量全部划给根目录对应的逻辑卷。根目录逻辑卷名称用lvdisplaylsblk确认,通常是/dev/mapper/centos-root

lvextend -l +100%FREE /dev/mapper/centos-root

这是最关键的一步:逻辑卷已经变大了,但文件系统还不知道。如果是ext4文件系统,执行:

resize2fs /dev/mapper/centos-root

如果是xfs文件系统,要改用:

xfs_growfs /

注意这两种文件系统的扩容命令完全不同。ext4用resize2fs指定逻辑卷设备,xfs用xfs_growfs指定挂载点。曾经遇到过有人给xfs的根分区跑resize2fs,结果报错不说,差点以为自己把系统搞坏了。最后执行df -h,你会看到根目录容量已经变成新盘扩展后的完整大小,全程系统没有重启,业务没有中断。

LVM这套机制一旦用熟了,磁盘扩容就从一个“高风险操作”变成了“日常小操作”。如果你现在正要重装系统,强烈建议在安装阶段采用LVM布局,给未来留足灵活性。

5. 高频踩坑记录:这些细节不注意,扩容容易变灾难

5.1 fstab写错导致系统无法启动

这是挂载操作里翻车率最高的问题。症状很典型:重启后系统进不了正常界面,卡在“emergency mode”或“maintenance mode”,提示找不到某个设备或挂载失败。

原因多数是fstab里UUID抄错、挂载点目录不存在、或者文件系统类型写错。处理办法:在紧急模式界面输入root密码,重新挂载根目录为可写状态:

mount -o remount,rw /

然后编辑/etc/fstab,把刚才加的那行注释掉或者修正错误。改完执行reboot,系统就能正常启动。

要避免这个问题,最好的习惯是每次改完fstab都执行一次mount -a测试。配置正确时没有任何输出,配置错误时当场报错,当场修正,不要拿生产服务器的重启来赌。

5.2 挂载后原目录里的文件“消失”了

很多新手会遇到这种情况:把新盘挂载到/data后,发现原来/data里的文件全都不见了,然后以为数据丢了,急得满头大汗。

其实数据没有丢。Linux的目录挂载逻辑是:一旦某个分区被挂载到目录A,目录A原本的内容就会被“遮挡”住,就像你往一个抽屉里塞进另一个抽屉,原来的文件还在,只是从当前视角看不到了。要找回原来的文件也很简单,先卸载新盘,旧数据就重新出现了。

正确流程应该是:先把旧数据同步到新盘,再完成挂载替换。如果你已经忘了同步就直接挂载了,也不用慌,卸载新盘、把旧数据rsync到临时挂载的新盘目录、再挂载回去就行。千万注意,在挂载状态下直接对/data目录执行rm -rf,删的是新盘里的数据,旧数据还在下面埋着,但如果你把挂载点目录本身删掉,操作就复杂了。

5.3 设备名不可靠,要用UUID而不是/dev/sdX

有人习惯在fstab里写/dev/sdb1,这在单盘环境下通常没问题,但一旦服务器有多块磁盘,或者磁盘被重新插拔过,设备名就可能发生漂移:原来的/dev/sdb变成/dev/sdc,导致系统启动时找不到正确的盘。

UUID是文件系统创建时生成的一个全球唯一标识,不会因为设备名变化而改变。所以fstab里统一使用UUID=xxx的写法是最稳妥的。查看UUID的命令就是前面用过的blkid /dev/sdb1。另外,对新格式化完的盘,blkid可能因为系统缓存没刷新而看不到UUID,这时候先partprobe /dev/sdb让内核重新读取分区表,然后重试。

5.4 挂载后的权限问题导致应用报错

挂载本身成功了,但业务应用连不上目录,数据读写不了。这类问题很多时候不是挂载的问题,而是权限的问题。新分区格式化之后,挂载点的属主、属组默认是root,如果你原来的目录属于mysql用户,挂载之后应用就会因为没有权限而报错。

解决方式很简单,挂载完成之后执行一遍chown把所有文件归属到对应的用户和组,或者根据实际场景在fstab里配置uid/gid挂载选项。顺带提一句:如果新盘是从Windows那边拿来的NTFS或exFAT格式,Linux虽然能通过ntfs-3g等方式读取,但性能和权限表现都不够好,不建议在Linux服务器上使用这类文件系统。原生ext4或xfs才是正确选择。

最后分享一点实用心得

用Linux这么多年,我最大的体会是:磁盘挂载本身不难,难的是对挂载概念的理解和对数据的敬畏。每次扩容前做好备份,操作时确认盘符无误,改完fstab执行mount -a验证,这“三板斧”能挡掉绝大多数翻车场景。另外,如果条件允许,从装系统开始就选择LVM布局,后面遇到根目录不够用,就是几条命令的事,完全不需要经历数据迁移和重启引导的惊悚过程。希望这篇记录能帮你少踩一些我踩过的坑,让磁盘扩容这件事不再是运维里的“高危动作”。

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

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

立即咨询