Ubuntu分区空间不足?迁移home目录与fstab永久挂载全攻略
2026/9/16 19:24:29 网站建设 项目流程

但凡在Ubuntu上装过双系统、工作开发机,或者用虚拟机跑Linux的人,十有八九都撞过同一个问题:当时装系统觉得“根目录给个30G够了吧,home分大一点”,结果半年后再看,根目录红了,或者反过来home不够用。更尴尬的是,分区表已经定死,重新分区代价极大,重装系统又心疼数据。

这篇文章就围绕“Ubuntu根目录/和用户目录/home分区太小”这件事来展开,核心不是教你删文件腾个三五G糊弄过去,而是把“重新挂载home以及其他目录”这套迁移逻辑讲透。先理解为什么分区会吃紧,再讲清楚怎么把/home、/var、/opt这类体积增长快的目录搬到更大的分区,最后用fstab实现开机自动挂载,从根上解决空间不足的问题。整个方案适用于双系统、单系统、虚拟机里的Ubuntu,甚至在WSL和开发板上也能参考同样的管理思路。

1. 分区太小的问题根源与解决思路

1.1 为什么根目录和home会越来越大

先说一个容易踩坑的认知:分区“够用”和“长期够用”是两回事。装系统时,/ 分区给个30G或50G,当时看起来绰绰有余,但真正用起来你就知道了。系统的日志文件(/var/log)、软件包的缓存(/var/cache)、snap应用、Docker镜像(/var/lib/docker)、还有Qt或Python项目编译产生的中间文件,全都在往 / 里面堆。我见过很多人的根目录莫名占掉40G,一查,光是snap目录就十几个G,Docker镜像又占十几个G,LLM或深度学习模型缓存再占十几个G,根目录瞬间就黄色告警了。

而/home分区的问题通常是反过来的——要么太小,因为当初把大头给了/,要么太大,但因为下载目录、桌面文件、各种摆拍不改的项目堆在里面,空间照样被填满。还有一种情况是,很多入门用户装了双系统以后,被“分给Linux 30G就够了”的教程误导,整个Ubuntu只分了一个根分区,连/home独立分区都没做。这样系统跑一段时间必然捉襟见肘。

1.2 核心思路:目录迁移+重新挂载,而不是盲目扩分区

面对分区太小,很多人第一反应是“能不能把分区拉大”。说实话,扩展分区本身可行,但要害在于:磁盘上的物理分区调整属于高风险操作,要么借助GParted Live启动盘做无损调整,要么在Windows下用傲梅分区助手之类的工具腾空间,整个过程要关机、要引导U盘,中间一旦断电或者操作失误,数据就不好说了。而且如果你用的是LVM(逻辑卷管理),虽然理论上可以直接lvextend扩容,但你当初没做LVM的话,这条路也被堵死了。

那有没有不动分区表、不装新盘也能从根本上解决问题的办法?有,而且思路非常简单——目录迁移 + 重新挂载

Linux的文件系统设计里,目录只是挂载点,你可以把某个目录(比如/home)从根分区的普通文件夹,迁移到另一个已经格式化的独立分区上,再把这个分区挂载到/home位置。这样,表面上路径没变,你的家目录还是/home/用户名,但实际存储落到了新的分区。操作系统和应用程序根本感知不到变化,根目录却瞬间释放出大量的空间。如果你手头有闲置分区,这是成本最低、风险最小的方案。

2. 动手前的准备工作

2.1 检查当前磁盘分区布局

先别急着操作,第一步是搞清楚磁盘到底长什么样。打开终端,依次运行下面几个命令:

df -h lsblk blkid

df -h用来查看当前的文件系统使用情况,重点看根目录/和/home分别挂在哪个设备上,已用百分之多少。lsblk能看到整个磁盘的分区结构,确认哪些分区是闲置的、哪些已经被挂载、哪些还有未分配的剩余空间。blkid则显示每个分区的UUID和文件系统类型,后面写fstab时要用到。

举个例子,假设输出是下面这样的:

NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT sda 8:0 0 238.5G 0 disk ├─sda1 8:1 0 512M 0 part /boot/efi ├─sda2 8:2 0 45G 0 part / └─sda3 8:3 0 193G 0 part

看到sda3没有被挂载,大小有193G,这就是理想的迁移目标。如果磁盘上没有空闲分区,而是整块盘都分配完了,那你得先压缩某个分区,或者在另一块物理硬盘上划出空间。判断标准就一条:找一个“没有挂载点、文件系统为空或可覆盖”的分区作为目标分区。

2.2 规划迁移方案与风险控制

迁移方案通常分两种:

  • 目标分区已有数据但可清空:直接格式化后挂载。
  • 目标分区是全新未分配空间:先创建分区,再格式化,再挂载。

无论哪种,你都需要在动手前想清楚三件事——备份、备份、还是备份。尤其是/home目录,你的文档、配置、SSH密钥、浏览器书签全在里面,千万不要“先操作再后悔”。

备份可以通过rsync或tar完成。推荐用rsync,比如把整个home目录同步到外置磁盘或者另一台机器:

rsync -avxP /home/ /media/backup_disk/

-a是归档模式保留权限和链接,-v是显示详细过程,-x不跨文件系统,-P显示进度并支持断点续传。备份完成后,再考虑怎么迁移。

另外特别提醒:如果你当前正开着图形桌面,把/home整个目录搬走的时候,会有很多进程正占用着里面的文件(桌面会话锁、正在编辑的文件、系统的xdg-user-dirs缓存),直接卸载会失败,直接拷贝也容易漏掉正在写的文件。最稳妥的方式是切换到tty文本终端(Ctrl+Alt+F3),或者用SSH远程登录执行操作,先退出图形会话再迁移。

3. 核心实操:将home目录重新挂载到新分区

3.1 创建文件系统并挂载临时分区

下面以“目标分区为/dev/sda3,容量193G”为例,走一遍完整流程。开始前先把目标分区格式化为ext4文件系统:

sudo mkfs.ext4 /dev/sda3

注意:mkfs.ext4会清空目标分区上的所有数据。如果这个分区原来有资料,务必先确认不需要了,或者已经备份,再执行格式化。

格式化完成后,建一个临时挂载点,把新分区挂上去,然后开始同步数据:

sudo mkdir -p /mnt/newhome sudo mount /dev/sda3 /mnt/newhome sudo rsync -avxP /home/ /mnt/newhome/

这条rsync会把原有/home目录下的所有内容,包括隐藏文件(比如.bashrc、.config、.ssh这些以点开头的文件),完整地同步到新分区。注意源路径末尾带不带斜杠有讲究:/home/ 会把home目录里面的内容拷贝到目标目录,/home 不带斜杠则会多包一层。我们在目标分区上期望的是“里面装着用户的目录”,所以用/home/是对的。

同步完成后,需要确认一下目录属主和权限是否正确。rsync加-a参数就会保留属主和权限,正常情况下不需要额外修改。如果你发现某些文件的所有者变成了root,说明命令执行时有人为干预了UID/GID,可以在确认旧home里用户ID后手动修复:

sudo chown -R 1000:1000 /mnt/newhome/用户名

1000通常是Ubuntu安装时创建的第一个普通用户UID,具体可以用id 用户名来查。

3.2 修改fstab实现开机自动挂载

数据拷贝完成后,先别急着删旧home。先把挂载关系写进/etc/fstab,让系统开机时自动把新分区挂到/home,然后再做切换测试。

获取目标分区的UUID:

sudo blkid /dev/sda3

输出类似:

/dev/sda3: UUID="abcdef12-3456-7890-abcd-ef1234567890" TYPE="ext4"

把这一行UUID记录下来。接下来编辑fstab:

sudo cp /etc/fstab /etc/fstab.bak sudo nano /etc/fstab

在文件末尾加一行:

UUID=abcdef12-3456-7890-abcd-ef1234567890 /home ext4 defaults 0 2

解释一下这一行各字段的含义:Device(UUID标识)、Mount Point(挂载点)、File System Type(文件系统类型)、Options(挂载选项,defaults就够用)、Dump(是否备份,0表示不dump)、Pass(是否开机检查文件系统,根目录设为1,非根分区设为2)。

保存退出后,先不要重启,依次执行:

sudo umount /mnt/newhome sudo mount -a

mount -a会读取fstab并尝试挂载所有未挂载的项。如果没有任何报错,再执行df -h,应该能看到/dev/sda3已经挂在/home下面了。这时候你打开文件管理器,你的家目录文件都在,路径也没变。

注意,这里有个重要的操作细节:你在当前会话里可能已经被“困住”了,因为/home已经被换成了新分区,但你的命令行当前工作目录很可能还在旧home目录的残留路径下。建议切到/tmp或者/root下再继续,防止正在使用旧目录的进程造成文件访问错乱。

3.3 旧home数据处理与回滚预案

确认新分区挂载正常、家目录文件完整可读以后,旧home目录的空间还在拖累根分区。但千万不要直接rm -rf /home。退休后的旧目录建议改个名,变成普通文件夹,不再作为挂载点:

sudo mkdir -p /media/old_home_backup sudo mount --bind /home /media/old_home_backup

不过说句实话,更干净的做法是这样的:先把fstab里加好的新分区挂载搞定后,把旧home里还没同步完、或者你怀疑漏掉的东西手动确认,然后用下面方式把旧目录里的内容挪走:

sudo mv /home /home.old sudo mkdir -p /home sudo mount -a

注意步骤有先后。先mv把旧目录改名,再建新的空/home目录,最后mount -a让新分区挂到/home。这个方法比直接删保险得多,旧数据还在/home.old里,万一新分区有问题还能回滚。如果确认新分区稳定运行了一两周,再sudo rm -rf /home.old释放空间。

回滚预案同样要清楚。假如切换后系统开机出现异常,进入紧急模式,你可以:

# 紧急模式里根文件系统是只读的,先重新挂载为读写 mount -o remount,rw / # 把fstab里新增的那一行注释掉,恢复原有home目录 nano /etc/fstab # 重启 reboot

然后执行mv /home.old /home恢复原状。整个流程很简单,但前提是:fstab备份一定要做,旧home一定不要删太早。

4. 其他目录的迁移与fstab自动挂载扩展

4.1 /var、/opt、/srv、/usr/local等大目录的迁移场景

不只是/home会空间紧张,在真实运维和开发环境中,/var才是真正的“空间杀手”。Docker的数据目录在/var/lib/docker,MySQL默认在/var/lib/mysql,PostgreSQL也放在/var/lib/postgresql,系统日志在/var/log。如果你把一些大型组件装到了/var,根分区的空间往往被它吃光。迁移/var的方法和/home如出一辙,但有个坑:系统几乎随时在写/var/log、/var/cache,直接在线rsync会导致数据不一致。

稳妥的路径是这样:先在tty文本会话下操作,把服务都要停掉,比如Docker、MySQL、系统日志服务:

sudo systemctl stop docker mysql postgresql 2>/dev/null sudo systemctl stop rsyslog sudo rsync -aXS /var/ /mnt/newvar/

这条rsync多加了个-S参数,用于处理稀疏文件(比如数据库文件里的空洞),避免把整块空间白白copy出来,迁移/var这类大目录时值得加上。

同步完成后,同样修改fstab,把新分区挂载到/var,然后重启。系统起来后再启动对应服务,基本就切换成功了。

/opt和/usr/local也是类似的道理。前者放很多大型商业软件,后者是手工编译软件默认的安装位置,这些目录适合作为迁移对象。相比/var,这俩没有进程高频写文件的问题,直接在tty下迁移即可。

4.2 用bind mount映射而不移动原数据

前面都是把整个目录搬走,还有一种更灵活的做法是bind mount(绑定挂载)。它的大致意思是:把某个目录“绑定”到另一个挂载点上,让两个路径指向同一份数据。典型场景是:你的Docker数据目录默认在/var/lib/docker,你不想动这个目录结构,但希望数据实际存在另一个大分区,可以这样操作:

sudo mkdir -p /data/docker sudo rsync -aXS /var/lib/docker/ /data/docker/ sudo mount --bind /data/docker /var/lib/docker

这种“目录重定向”不需要格式化原分区,也不需要修改原目录的数据位置,只需要在fstab里加一行:

/data/docker /var/lib/docker none bind 0 0

bind mount的优势是灵活、见效快,特别适合nginx站点目录、Docker数据目录、samba共享目录等场景。但它不会自动帮你迁移数据,你得自己把原数据同步过去,而且系统里会出现两份“路径引用”,排错时别弄混。

4.3 多用户多磁盘场景:home独立分区的经验建议

如果你有多个Linux发行版共存,或者有多块硬盘,规划home目录时要留意不同系统对UID/GID的默认值可能不一致。比如一个系统的用户UID是1000,另一个系统的用户UID可能是1001。直接把同一块数据盘挂载给两个系统使用,文件属主会乱套。建议在/etc/fstab里为特定用户指定uid和gid挂载选项,或者统一维护一套用户ID分配规范。

如果你想把远程NAS上的目录挂到本地home下使用,那fstab又要换一套参数。比如CIFS/SMB共享目录的挂载,需要加上_netdev和nofail,防止网络未就绪时影响开机启动:

//192.168.1.100/share /home/用户名/nas cifs username=user,password=pass,uid=1000,gid=1000,iocharset=utf8,_netdev,nofail 0 0

这个场景虽然和本地分区迁移不同,但思路是一致的:都是通过fstab把外部存储资源挂载到目录层级里。我在实际工作中遇到过很多“重启后共享目录没挂上”的问题,绝大多数都是因为漏了_netdev参数,导致systemd在网络文件系统就绪前就尝试挂载,结果失败后不再重试。加上nofail,就算挂载不上系统也能正常进桌面,不会卡在启动阶段。

5. 常见问题与排查技巧实录

5.1 fstab配置错误导致开机进不了桌面

这是迁移home后最容易翻车的地方。症状很典型:开机卡在一个蓝底黑字的提示“A start job is running for /home(时长倒计时)”,或者直接进入emergency mode。

原因通常是三类:UUID写错、挂载点目录不存在、文件系统类型不对(比如把ext4写成了xfs)。排查思路分两步:

第一步,在emergency mode中,确认根文件系统只读状态,然后重新挂载为可写:

mount -o remount,rw /

第二步,查看fstab内容,确认UUID是blkid查出的真实值,确认/home目录存在(如果之前mv过后没建新目录,就会因为这个挂不上),确认文件系统类型和分区实际格式一致。

改好以后执行reboot。如果只是小错误,系统马上恢复正常;如果还是进不去,那就走回滚预案:把刚加的fstab行注释掉,重启后先恢复到原状,再重新一步步排查。

5.2 数据目录迁移后应用无法访问

常见的报错有两类:一类是权限permission denied,比如迁移了MySQL的数据库目录,但新分区上的数据目录所有者是root,MySQL进程跑起来没权限打开数据文件。这种情况直接把目录属主改成mysql用户即可:

sudo chown -R mysql:mysql /var/lib/mysql

另一类是路径硬编码问题。有些软件在配置文件里写死了绝对路径,你bind mount之后路径没变,但从原目录移动数据后,软件可能记住了旧的物理路径或inode信息,重启服务或重启机器就好。Docker容器尤其如此,容器数据目录迁移后,最好先docker-compose down再up,让容器重新读取挂载信息。

5.3 空间明明有但显示满了

迁移完成后,你可能会遇到一个“幽灵空间”问题:df -h显示分区还有几十G空闲,但目录里怎么找都找不到空间消耗在哪里,甚至系统提示磁盘已满。

这种情形大概率是inode耗尽,或者文件已被删除但进程仍占用。前者用df -i查看inode使用率,如果100%了,删除大量小文件(比如缓存目录、php session、npm缓存)来释放;后者用lsof | grep deleted查看被删除但仍被进程占用的文件,重启对应进程或直接重启系统,空间才能真正释放出来。

还有一个小坑是删数据时被进程不断写入新文件,比如迁移没停服务的MySQL日志目录,你一边删它一边写,空间永远不会减少。所以排查空间问题之前,先把相关服务停掉,再检查。

5.4 磁盘完全没有空闲分区,怎么腾出空间

如果在lsblk里看不到任何未挂载分区,或者未分配空间已经被用尽了,那就需要从其他分区里挤出空间来。常见做法是:

  • 在Windows下用傲梅分区助手压缩一个不太重要的分区(比如D盘),腾出未分配空间,然后重启进入Ubuntu,用gparted把未分配空间划到目标分区。
  • 或者在Ubuntu里用GParted工具直接调整分区大小,操作时注意先用live USB启动,不要在系统挂载该分区时调整。

调整完之后再重新执行前面的迁移流程。这种方法本质上是“先扩大物理分区,再迁移或扩容逻辑空间”,和直接迁移目录并不冲突,二者配合使用效果更好。

6. 另一种更省事的方案:LVM扩容(有条件时推荐)

如果你装系统时用了LVM(逻辑卷管理),那么扩容根本不用这么折腾。Ubuntu桌面版默认不一定启用LVM,但服务器版在安装时勾选“使用LVM”选项后,后续所有分区都被卷组管理,扩容命令行几秒钟就能完成。

LVM扩容home的逻辑是这样:

# 查看卷组剩余空间 sudo vgdisplay # 把剩余空间扩展给home逻辑卷,比如增加40G sudo lvextend -L +40G /dev/ubuntu-vg/home # 调整文件系统大小(ext4) sudo resize2fs /dev/ubuntu-vg/home

整个过程无需卸载、无需重启、无需迁移目录,一条lvextend加一条resize2fs就搞定了。如果你现在还没装系统,但预估以后磁盘空间会很紧张,强烈建议用LVM方案装系统。分区表规划上,稍微多预留一些“未分配空间”给将来扩容,绝对比日后临时抱佛脚要轻松得多。

对于已经装好系统、又碰巧没有LVM的用户,前面的“目录迁移+重新挂载”就是最稳妥、最通用的替代方案。两者从操作系统角度来说,一个是从卷层面扩展,一个是从挂载层面重定向,最终达到的效果是一致的:让/home“真正”拥有一块更大的空间。

写在最后,想多说几句经验

用这套方法折腾过很多次之后,我总结下来最值得记住的不是命令,而是四个字——留有余地。

不管是分区还是迁移,永远别走在悬崖边上操作。fstab改动前随手cp一份备份,旧home保留至少一周再清理,目标分区格式化前反复确认设备号没写错(sda和sdb搞混的教训太惨痛了)。这些“多余”的谨慎行为,在一切顺利的时候看起来浪费时间,但只要踩一次坑,你就能体会到它们的价值。

另外再分享一个实用小技巧:确定要做目录迁移时,尽量选择rsync而不是cp -a。rsync支持断点续传、显示进度、同步时可排除特定目录,迁移超大home目录时如果中途断网或中断,重新执行命令就能从断点继续,而不是推倒重来。对于习惯了图形界面操作的朋友来说,rsync每天花几分钟了解一下,以后会省下大把的时间。

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

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

立即咨询