尧图精选

Ubuntu根目录与/home空间不足?重新挂载方案一劳永逸

🕒 发布时间:2026/10/1 6:04:57 📁 来源:尧图网络
Ubuntu用着用着根目录 / 和 /home 分区双双爆红这是我混各种Linux群里见过次数最多的求助帖。明明装机的时候觉得100G绰绰有余结果Docker镜像、虚拟机磁盘、缓存文件一跑起来几个月就见了底。折腾了这么多年我自己的心得是与其天天想着清理垃圾不如一次性把分区和挂载关系规划好。这篇文章就把我处理Ubuntu根目录和/home分区太小的完整思路写出来重点讲明白重新挂载这套操作——什么时候该用、怎么安全地把/home以及其他目录换到大分区或新磁盘上、以及挂载完之后有哪些特别容易翻车的坑。全程按我自己实操的顺序来命令直接复制就能用新手也能跟下来。1. 先把根目录满了这件事拆开不是所有的目录都挤在同一个分区1.1 目录树和分区的关系先搞懂挂载是什么很多朋友看到df -h里/那一行红了第一反应是我系统盘满了其实得先搞清楚一个问题Linux 的目录树只是一个逻辑视图真正决定空间的是分区挂载在哪个目录。举个例子你就明白了。假设磁盘上有一个 20G 的分区挂载到了/另一个 80G 的分区挂载到了/data。你往/home/你的名字/下载/里写文件如果/home没有独立的分区那么这个文件占用的就是 20G 那个根分区的空间但如果往/data里写文件占用的就是 80G 那个分区的空间。所谓挂载mount就是把一个分区/设备绑定到目录树的某个节点上。你访问这个节点实际读写的是那个分区的数据。所以根目录满了不代表整个系统没空间了——很可能你的磁盘上还有大片空间躺在其他分区里而系统的空间分配根本不均匀。这就解释了为什么你能搜到各种重新挂载的教程不是要重新装系统而是要把占地方的目录挪到有富余的分区上去。1.2 判断你的 /home 是否真的独立分区在进行任何操作前先要回答一个问题/home到底有没有独立分区很多人被分区太小困扰但其实他压根没有独立的/home分区/home只是根分区里的一个普通目录。判断方法非常直接df -h /home df -h /如果这两条命令输出的设备是同一个比如都是/dev/sda2说明/home没有独立分区它就是在吃根分区的空间。如果输出的是不同设备比如/dev/sda2挂在//dev/sda5挂在/home那才有独立分区太小的问题。再看一下挂载关系会更直观mount | grep /home # 或者 findmnt /home这里多说一句Ubuntu 默认安装时很多时候只分了一个/分区加一个 swap根本没有独立的/home。这种情况下系统只有一个根分区你看到的/home目录只是根分区下面的一层。所谓home分区太小本质是根分区不够大。这种场景的处理思路和独立/home分区太小会有一点差别后面我会展开。1.3 找到根目录空间的真正主人不管要不要重新挂载你都得先知道什么在吃磁盘。一条命令看全局sudo du -x -h --max-depth1 / 2/dev/null | sort -h-x参数的意思是只统计当前文件系统内的目录不会跑到其他挂载分区里去统计特别重要。输出的结果会按占用大小排序一眼就能看出大头是谁。根据我的经验根目录空间告急时常见的大户有这么几个/var/lib/docker——Docker镜像和容器层全在这里动不动几十G/var/lib/libvirt/images——KVM虚拟机的磁盘镜像/var/log——系统和应用日志journald积攒起来也吓人/home——用户数据/opt——各类手动安装的软件/usr——系统软件和库这个一般不建议动如果发现du统计出来的总量比df显示的已用空间小很多说明有已删除但仍在被进程占用的文件。这种情况可以用sudo lsof L1查看找到后重启相关服务就能释放。这个坑我后面会专门讲。搞清楚到底什么在占空间你才知道需要重新挂载的到底是/home还是/var/lib/docker还是别的目录。2. 动手前的磁盘体检三条命令看清你的真实格局2.1 df、lsblk、findmnt 的组合用法准备动刀之前一定要把当前的磁盘格局看明白。我的习惯是先跑三组命令花不了半分钟df -hT lsblk -f cat /etc/fstabdf -hT能看出每个已挂载分区的容量、已用、可用空间以及文件系统类型lsblk -f能列出所有块设备、分区、文件系统类型、UUID和挂载点这是最核心的一张全景图cat /etc/fstab则告诉你系统开机时按什么规则挂载这些分区。再结合findmnt精确查看某个目录当前挂载在哪个设备上、用什么选项挂的findmnt /home findmnt --target /var/lib/docker如果你在lsblk -f里看到某些分区没有挂载点说明它们当前没被挂载可能是之前手动挂过、也可能一直闲置这些都可以作为后续迁移的备选目标。2.2 文件系统类型影响你接下来能做什么df -hT里的 Type 列很多人会忽略可它直接决定了你能用什么手段放缩分区ext4最常见可缩可扩。扩展时可以用resize2fs在线完成缩小时一般要在 Live 环境或卸载状态下操作。xfs只能扩大不能缩小。扩容用xfs_growfs但缩小编排很麻烦。btrfs有自己的子卷subvolume机制和传统分区思路不一样。swap交换分区不在本文讨论范围。为什么强调这个因为分区太小的解决方案和文件系统强相关。如果是 ext4 且旁边有空间可以扩容如果是 xfs只能考虑加盘或重新挂载目录。提前确认格式能省下一堆折腾时间。2.3 先看 /etc/fstab别重复挂载踩坑/etc/fstab是开机挂载的配置文件动手前必须看不然可能出现两种情况一是你新挂载的目录在 fstab 里已经有一条记录改了半天实际没生效二是你只手动mount了没写 fstab重启后又打回原形。fstab 每行有六列格式大致是设备 挂载点 文件系统类型 挂载选项 dump fsck比如UUIDabc123... / ext4 defaults 0 1 UUIDdef456... /home ext4 defaults 0 2 UUIDghi789... swap swap defaults 0 0越是新手越容易在写 fstab 这一步栽跟头。我的建议是动手前把当前 fstab 内容完整备份一份。sudo cp /etc/fstab /etc/fstab.bak后面如果写错了至少还能用备份救回来。3. 扩容方案的取舍加盘、压缩相邻分区、还是在线扩LVM重新挂载不是唯一解法有时候直接扩分区更省事。我把常见的场景和对应方案梳理一下你先判断自己属于哪种情况再决定走哪条路。3.1 场景一虚拟机或者有富余磁盘空间加一块新盘最省心如果你是在 VMware、VirtualBox、KVM 里跑的 Ubuntu加一块新虚拟磁盘是最省心的方案风险也最低。操作思路是关闭虚拟机 → 在虚拟机设置里添加一块新磁盘比如 100G→ 开机后在 Ubuntu 里让内核识别新磁盘。新加的虚拟磁盘有时需要手动刷新才出现可以用echo - - - | sudo tee /sys/class/scsi_host/host0/scan或者干脆重启一次最省事。然后lsblk应该就能看到新设备了比如/dev/sdb或者/dev/nvme0n1。后续就是分区、格式化、迁移数据、挂载也就是本文第4章的内容。为什么我优先推荐加盘因为它完全不动原磁盘的分区布局。原盘上哪怕是系统分区也保持原样万一迁移过程中出了什么问题把新盘一拔系统照跑不误。物理机上如果你想加第二块硬盘道理也一样。3.2 场景二物理机且有未分配空间考虑 GParted 从 Live USB 操作如果是物理机且磁盘上有未分配空间正统做法是用 GParted 从 Live USB 启动把相邻分区缩小腾出空间再扩大根分区或/home分区。思路大致是准备 Ubuntu 安装U盘或 GParted Live 盘从U盘启动进入 Live 环境打开 GParted右键需要缩小的分区比如/data选择 Resize/Move让它变小把腾出来的未分配空间向右移动紧挨着目标分区右键目标分区比如/选择 Resize拉大Apply 应用等它跑完听起来不难但这里有个很现实的限制根分区在磁盘上的位置往往不在空闲空间旁边。比如/在磁盘开头后面是 swap再后面才是空闲区那么中间有 swap 挡着/就没法直接扩除非你先把 swap 移走。这种操作在 GParted 里会涉及大量数据搬移耗时很长也有一定风险。所以我的判断是如果你对 GParted 不熟或者根分区被其他分区夹在中间倒不如重新挂载目录来得干净。只把占空间大的子目录挪到别处分区系统分区一个字节都不用动。3.3 场景三你的系统本来就用了LVM直接在线扩如果你在安装 Ubuntu 时选了 LVM 方案比如默认的使用 LVM选项那扩容是三个场景里最简单的因为逻辑卷可以在线扩展不需要卸载、不需要重启。先用几条命令看卷组和逻辑卷的情况sudo pvs sudo vgs sudo lvs如果是根逻辑卷空间不够直接执行sudo lvextend -l 100%FREE /dev/ubuntu-vg/ubuntu-lv sudo resize2fs /dev/ubuntu-vg/ubuntu-lv第一条命令把卷组里所有剩余空间都分给根逻辑卷第二条命令让 ext4 文件系统扩展到整个逻辑卷。如果是 xfs用xfs_growfs /。如果物理卷本身也没空间了就得先加盘# 假设新盘是 /dev/sdb sudo pvcreate /dev/sdb sudo vgextend ubuntu-vg /dev/sdb sudo lvextend -l 100%FREE /dev/ubuntu-vg/ubuntu-lv sudo resize2fs /dev/ubuntu-vg/ubuntu-lvLVM 的灵活之处就在于它把物理磁盘空间和逻辑分区空间解耦了。但前提是你当初装了 LVM很多手动分区方案并没有这个待遇。没有 LVM 的话老老实实看场景一和场景二。3.4 为什么重新挂载目录有时候才是最优解我见过不少人折腾了半天 GParted最后发现根分区被 swap 和/boot夹在中间根本没法爽快地扩大白忙活一场。这时候重新挂载目录的优势就体现出来了不动根分区本身风险集中在迁移数据和改 fstab两步只把占用大的目录/home、/var/lib/docker、/opt挪到有空间的分区其余系统文件保持原样对物理机、虚拟机、云主机都适用后续如果新分区又不够了再挂一个更大的分区把目录切过去就行灵活性高这也是为什么这个标题的教程能在各种社区反复出现——它是处理分区不合理时最通用、最不需要赌运气的办法。4. 重新挂载 /home 和其他目录的完整流程从分区到fstab这一章是重头戏。我以新增一块磁盘/dev/sdb把/home迁移过去为例子完整走一遍。其他目录的迁移方法完全一样把/home换成目标目录即可。4.1 创建新分区和文件系统先确认新磁盘设备名lsblk假设看到/dev/sdb是一块空盘。给它创建 GPT 分区表并建立一个占满整个磁盘的分区sudo parted /dev/sdb --script mklabel gpt mkpart primary 0% 100%然后格式化sudo mkfs.ext4 -L home /dev/sdb1-L home是给文件系统一个卷标方便识别。文件系统类型我建议用 ext4兼容性最好如果这块盘要放特别大的文件比如虚拟机镜像xfs 也不错但 xfs 后续没法缩小要提前想好。临时挂载验证一下分区没问题sudo mkdir -p /mnt/test sudo mount /dev/sdb1 /mnt/test能正常挂载、df -hT /mnt/test能看到容量说明分区没问题先卸载准备正式迁移sudo umount /mnt/test4.2 用 rsync 把 /home 原样搬到新分区这一步是整个流程里最关键的。很多人图省事用cp -r结果复制出来权限全乱、符号链接断掉、ACL丢失。必须用 rsync。先把新分区挂到临时挂载点sudo mkdir -p /mnt/newhome sudo mount /dev/sdb1 /mnt/newhome然后执行sudo rsync -aXS --numeric-ids --infoprogress2 /home/ /mnt/newhome/这几个参数每个都有讲究-a归档模式保留权限、属主属组、时间戳、符号链接等-X保留扩展属性ACL-S处理稀疏文件避免稀疏文件白白占满空间--numeric-ids按数字ID保留用户/组避免不同机器上用户名映射错乱--infoprogress2显示总进度让你心里有数注意/home/结尾的斜杠。rsync 对结尾斜杠非常敏感/home/表示复制目录里的所有内容/home则会连目录本身一起复制导致目标路径变成/mnt/newhome/home后面挂载时会嵌套目录特别别扭。复制完成后对比一下两边数据量和文件数du -sh /home /mnt/newhome find /home -type f | wc -l find /mnt/newhome -type f | wc -l数字差的离谱就说明漏了什么差十几二十个文件也可能是隐藏文件没算上重点看 du 的大小和文件数大致量级。4.3 把旧目录让出来新分区正式上位数据复制完成后不能直接把新分区挂到/home上就完事——因为旧/home还在原地如果你直接把新分区挂上去旧数据不是消失了而是被遮蔽了。正确做法是先把旧目录挪走。先把新分区卸载掉sudo umount /mnt/newhome把旧/home改名留作后路sudo mv /home /home.old这里 mv 只是改目录名不涉及跨分区复制瞬间完成。然后创建新的空目录并挂载新分区sudo mkdir /home sudo mount /dev/sdb1 /home马上验证一下df -h /home ls -la /home这时候/home应该显示挂载在/dev/sdb1并且能看到你原来的用户目录。先别急着删/home.old等系统重启确认没问题了再清理。这就是为什么前面要给旧目录改名而不是直接删除——万一新分区数据有问题mount到其他目录mv 回去就能恢复原状有后悔药吃。4.4 写入 fstab 实现开机自动挂载手动挂载只是临时的重启就失效。要让系统开机自动挂载得写进/etc/fstab。先获取新分区的 UUIDsudo blkid /dev/sdb1然后编辑 fstabsudo nano /etc/fstab在末尾加一行UUID上一步查到的UUID /home ext4 defaults,nofail 0 2各列的含义前面说过这里重点解释两个容易犯错的地方。第一必须用 UUID 而不是/dev/sdb1。设备名在系统里不是固定的比如你以后加了块新硬盘原来的/dev/sdb可能变成/dev/sdc系统就找不到设备了。UUID 是文件系统创建时生成的唯一标识基本不会变。第二加nofail选项。这个选项的意思是如果设备不存在开机时跳过它而不是卡在紧急模式等你处理。对数据盘来说非常实用。写好后测试一下 fstab 是否正确sudo umount /home sudo mount -amount -a会读取 fstab 并挂载所有满足条件的条目。如果没有报错df -h /home显示正常说明配置没问题。然后是终极验证——重启sudo reboot重启后确认/home挂载正确、用户能正常登录、家目录文件都在就可以清理旧数据了sudo rm -rf /home.old我个人的习惯是让/home.old留几天再删等新分区稳定了再说。4.5 其他目录怎么挂比如 /var/lib/docker、/opt、/srv把/home换成其他目录流程一模一样。但有几个额外注意点。比较适合重新挂载的目录见下表目录常见占用原因注意事项/home用户桌面文件、下载、文档迁移前确认没有用户正在使用最好在文本模式操作/var/lib/dockerDocker镜像、容器、卷挂载选项必须含exec且文件系统支持 overlay2/var/lib/libvirt/images虚拟机磁盘镜像大文件场景优先考虑xfs/var/log系统日志、journal迁移后重启 journald/rsyslog否则空间不释放/opt手动安装的大型软件挂载选项要支持 exec可能有绝对路径引用/srv网站、FTP等数据权限和属主需要保留比如/var/lib/docker是 Docker 的数据目录迁移时sudo systemctl stop docker sudo rsync -aXS --numeric-ids /var/lib/docker/ /mnt/newdocker/ sudo mv /var/lib/docker /var/lib/docker.old sudo mkdir /var/lib/docker sudo mount /dev/sdb1 /var/lib/docker # 编辑 /etc/fstab 加对应行然后 sudo systemctl start docker注意如果你把挂载选项写成了noexecDocker 起容器时直接报权限错误排查半天才发现是 mount 选项的问题。挂载/var/lib/docker这类需要执行程序的目录选项保持rw,exec就对了。另外还有个最常见的 rsync 陷阱迁移/var这种目录时有人会写rsync -a /var /mnt/new结果目标目录变成/mnt/new/var后面挂载时挂的却是/mnt/new导致目录层级错乱。还是那句话注意结尾斜杠。5. 挂载之后的翻车现场从进不去系统到文件全没了这一章是我最想写的。重新挂载的教程一搜一大把但挂载完翻车怎么救很少有人说清楚。我把自己踩过和见过别人踩的坑都列出来你遇到的时候心里有数。5.1 开机卡在紧急模式fstab 写错的处理办法fstab 写错最常见的后果是开机后进不了桌面直接进入 emergency mode 或者提示dependency failed。一般是 UUID 抄错、设备名写错、或者挂载点不存在。先别慌数据不会因为你写错一行 fstab 就丢。处理办法在紧急模式下输入 root 密码或者按提示直接回车进入维护模式然后以读写方式重新挂载根分区mount -o remount,rw /注释掉或修正 fstab 里那行可疑配置nano /etc/fstab把出问题的行前面加个#注释掉保存重启系统就能正常进来了。如果系统要求 root 密码但你又忘了密码那就得从 Ubuntu Live USB 启动挂载系统根分区后直接进去改 fstabmount /dev/sda2 /mnt nano /mnt/etc/fstab所以前面反复强调改完 fstab 后先mount -a测试加nofail选项备份 fstab。这三件事做到位基本不会经历这个惊吓。5.2 登录进去发现文件全没了挂载点遮蔽这是最吓人的一个坑但也是最好笑的——因为数据根本没丢。现象是新分区挂到/home后进入桌面发现 home 下是空的或者少了以前的文件瞬间血压升高。真相是你之前没有复制数据或者复制到了错误位置然后直接把新分区挂载到了/home把旧/home目录遮蔽了。Linux 挂载点就是这样一个逻辑分区挂到目录上后你访问这个目录看到的是分区里的内容原目录里已有的文件并不是被删除只是暂时不可见了。验证方法很简单sudo umount /home卸载后马上ls -la /home旧数据应该又出现了。所以标准流程里我特别强调先复制到临时挂载点/mnt/newhome验证数据没问题然后mv /home /home.old、mkdir /home、再正式挂载。这样每一步都可见、可回退就不会出现文件全没了这种吓人的情况。5.3 权限、ACL与AppArmor的连环问题如果迁移时 rsync 没用-a会出现一个很典型的问题新挂载的/home下所有文件和目录的属主变成了root:root用户登录后看到家目录空空如也或者能进去但完全没权限写文件。有些用户甚至连 SSH 登录都会被拒因为~/.ssh的权限和属主不对sshd 会拒绝信任它。解决办法是恢复属主关系sudo chown -R uid:gid /home/用户名uid 和 gid 一般用id 用户名查询。如果不想每个用户单独处理可以循环跑一遍家目录里.ssh目录要特别注意权限通常应该chmod 700 ~/.ssh、chmod 600 ~/.ssh/authorized_keys。推荐做法是复制时就用rsync -a保留所有属性从源头避免。Ubuntu 上 AppArmor 一般不会因为你换个挂载点就出问题但如果你迁移的是 Docker、数据库这类对挂载选项敏感的服务记得检查findmnt -o OPTIONS确认挂载不是noexec、nosuid、nodev这类受限模式。5.4 进程还握着旧文件句柄空间怎么没释放迁移完、也删了/home.old结果df -h一看根分区空间还是满的。这个坑最容易让人摸不着头脑。原因是有些进程在你迁移前就打开了旧目录里的文件句柄。文件删除后只要进程还持有句柄空间就不会释放。典型的就是系统日志服务比如 rsyslog 和 systemd-journald它们会长时间持有/var/log下的文件。排查方法sudo lsof L1看到很多deleted标记的文件就是这种情况。解决办法很简单重启相关服务或者直接重启系统sudo systemctl restart rsyslog sudo systemctl restart systemd-journald如果迁移的是/var/lib/docker重启 docker 服务基本能解决。实在不放心就重启一次反正已经迁移完成了重启也是终验。6. 从根源上避免分区太小装机时就该做好的空间规划6.1 推荐的分区方案折腾过这一轮之后我的体会是重新挂载是补救手段真正省心的是装系统时就做好规划。个人推荐的分区思路是根分区/50G~80G 足够。系统、软件、库放在里面这个量级很少会跑满/home单独分区把大部分空间都给用户数据用swap如果内存够大16G以上swap 给几个G意思一下就行或者干脆用 swapfile如果清楚自己会用 Docker 或虚拟机提前给/var/lib/docker或/var/lib/libvirt/images规划独立分区这套方案的好处是根分区和用户数据互不挤占缓存、日志、镜像、虚拟机文件各自有家不会再出现根目录爆了但 home 还空着的畸形局面。6.2 把扩容变成日常可操作的事如果你选择了 LVM后续扩容的主动权会大很多。逻辑卷可以在线扩大不用关机、不用卸载、也不用 Live USB。就算磁盘物理空间不够了加块新盘pvcreate、vgextend、lvextend、resize2fs四步走十几分钟搞定。哪怕没装 LVM也可以在系统里养成习惯周期性跑一下df -h和du盯着增长最快的目录。空间告急时第一时间判断是哪个目录的问题再决定是用 GParted 调整分区、加盘重新挂载还是借 LVM 在线扩。就我自己而言现在装机器不管是物理机还是虚拟机都会优先选 LVM 方案同时把 /home 单独分出去Docker 数据目录也尽量用独立分区。这套组合拳下来我已经很久没被根目录满了这种问题追着跑了。希望这篇文章能让你把分区和挂载这件事看得明明白白下次遇到空间不够不用再靠删缓存碰运气。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →