明明删了 CentOS 虚拟机里的日志、缓存,df -h 一看空间还是没变,心里直接冒出问号。CentOS虚拟机清理后空间不释放,核心原因是文件系统把磁盘块标记为“可写入”,但底层存储层无论是 LVM 逻辑卷、分区还是宿主机上的 qcow2 镜像依然把那些数据块当作已占用,所以空间“消失”得很冤。 接下来聊一聊真实排查路径。
为什么 CentOS 虚拟机删了文件,可用空间却没增加?
先别急着重启虚拟机,多数情况下,文件确实删了,但空间被“扣”在另一个层面,2010 年后主流 LVM 和稀疏镜像机制都有这个“迟钝”特性。
文件被进程“咬住”不放手
这是最常见的原因,你在 CentOS 里删除一个正在被写入的日志文件,/var/log/messages,文件系统里没它了,但运行中的 rsyslogd 或系统服务还握着旧文件句柄,Linux 会把该文件占用的空间保留到最后一个进程关闭文件描述符为止,这种现象在日志系统里尤其频繁,一个长时间不重启的 CentOS 虚拟机经常因此丢掉几个 GB。
- 使用
lsof +L1找到已删除但仍被占用的文件。 - 确认对应 PID 后,重启该服务或杀掉进程,空间才会真正交还给文件系统。
LVM 逻辑卷“只缩不缩”
如果你用 LVM 装 CentOS,情况更要小心。df -h 看到的是逻辑卷内部的可用空间,vgs 看到的是物理卷和卷组的空间,你在逻辑卷文件系统里删文件,只是腾出文件系统里的空闲块,LVM 本身不会自动收缩逻辑卷,除非跑 lvreduce,否则卷组的剩余空间永远不变,行业共识是:Linux 的删除操作只影响文件系统元数据,不影响块设备层的容量分配。
分区表没重新读取
如果你在虚拟机里扩展了虚拟磁盘,但分区依然按旧大小识别,清理后空间看起来像被“吃”了,这在扩容后特别常见,df 不会自动认识新块设备,除非跑 partprobe 或 resize2fs。
CentOS 虚拟机清理后空间不释放的排查步骤

与其瞎猜,不如按顺序查,每一步都能定位到具体领域。
第一步:区分文件系统空间与设备空间
先跑三条命令,把视角拉开:
df -h /:看文件系统里的可用空间。lvs:看逻辑卷的分配状态。vgs:看卷组里还有多少物理容量。
df 已经释放但 vgs 剩余空间没变,说明已经进入 LVM 收缩范畴。df 都没释放,优先查进程占用和 journal 日志。
第二步:用 lsof 找回“幽灵文件”
在 CentOS 终端执行:
lsof +L1 | grep deleted
如果输出了一些路径带 (deleted) 的文件,/var/log/messages (deleted),直接用 lsof 显示的 PID 去处理:
systemctl restart rsyslog
如果是 Java 进程或其它服务,可以 kill -HUP PID 让它重新打开文件,这一招能解决相当一部分空间不释放的问题。
第三步:清理 systemd journal 日志
CentOS 7 往后的系统默认把运行日志交给 journald,它占用的空间经常超乎预期,执行:
journalctl --vacuum-size=200M
只保留 200MB 日志,比手动删 /var/log/journal 安全得多,也可以设置 SystemMaxUse 限制未来日志体积,多数情况下,这一步就能释放几个 GB。
第四步:清理 yum 缓存
/var/cache/yum 是另一个空间黑洞,运行:
yum clean all rm -rf /var/cache/yum
注意别在删完后立刻看 df 就下结论先检查有没有进程仍在使用缓存目录。
宿主机上的 qcow2 镜像不自动收缩怎么办?
这是 CentOS 虚拟机场景中最让人头疼的一点,也是最容易忽略的一环,你在虚拟机内部把空间删干净了,df 也正常了,但回到宿主机上 ls -lh 那个 .qcow2 文件,体积依然和之前一样大。

稀疏文件原理
qcow2 和 vhd 都支持稀疏文件:文件内部只有实际写入数据的块才分配物理存储,你删除文件时,虚拟机内的文件系统把块标记为“空闲”,但 qcow2 并不知道这些块已经没用了,它会把“空闲”状态继续保留为已分配,所以宿主机层面空间不会变。
让虚拟机内支持 discard 并执行 fstrim
CentOS 7.3 以后的发行版内核都支持块设备丢弃命令,只要虚拟机磁盘接口支持 discard(如 virtio-blk 且宿主机配置开启),就可以在 CentOS 内部执行:
fstrim -v /
这个命令会通知底层存储哪些块已经空闲,宿主机上的 qcow2 随即收缩,不过要注意,使用默认的 ext4 或者 xfs 都能配合 fstrim,但如果你的虚拟机磁盘文件是 raw 格式,则通常不需要这一步,因为它本来就不含额外元数据。
用 qemu-img convert 重建镜像
如果你的宿主机没有开 discard 预算,qcow2 在 NFS 存储上,那 fstrim 大概率没用,老老实实走离线收缩路线:
systemctl poweroff 虚拟机 qemu-img convert -p -O qcow2 old.qcow2 new.qcow2
这条命令会重新复制有效数据块,丢弃所有未使用空间,转换完成后,把 new.qcow2 改名为正式镜像再启动,对于达到几十 GB 的旧镜像,收缩效果立竿见影。
使用 virt-sparsify 更省事
如果你装了 libguestfs-tools,可以离线执行:
virt-sparsify --in-place old.qcow2
它会直接处理现有镜像,不需要复制出新文件,但注意 --in-place 模式不支持 raw 格式,操作前记得备份,毕竟是对磁盘元数据的直接改写。
处理 LVM 卷时,清理后空间不释放的第二步走
在 CentOS 虚拟机里,df 和 lvs 是两个世界,如果你确认文件系统已经释放,但 LVM 卷组空间不够,说明需要手动收缩逻辑卷。
先卸载或缩小文件系统

ext4 文件系统要在线收缩是风险操作,生产环境务必先备份,停机后用启动盘或 live 环境操作更稳妥,重点流程:
umount /dev/centos/root e2fsck -f /dev/centos/root lvreduce -L 50G /dev/centos/root resize2fs /dev/centos/root
XFS 只支持收缩,不支持在线缩小,所以只能在卸载状态下操作,这里要格外留意,别一删文件就让 LVM 自动收缩它永远不会自动动。
收缩物理卷
逻辑卷收缩以后,卷组的剩余空间还是游离的,如果需要让整块物理磁盘腾出空间给宿主机,继续跑:
pvdisplay pvmove /dev/sda2 /dev/sda1 pvresize --setphysicalvolumesize 50G /dev/sda2
做完这些,虚拟机的底层块设备才真正瘦下来。
Q&A:CentOS 虚拟机清理后空间不释放的常见疑问
问:为什么重启 CentOS 虚拟机后,df 空间还是没增加?
重启能解决一部分被进程占用的文件,但如果是 qcow2 稀疏文件或 LVM 未缩减,重启完全无效,需要按上面步骤先查 lsof 或 journald,再处理 LVM 和镜像文件层。
问:fstrim 与 qemu-img convert 哪个更好用?
两个方案解决不同层次的问题,fstrim 只适合宿主机支持并开启 discard 的稀疏文件场景,速度快,不用停机;qemu-img convert 不依赖宿主机配置,但需要关机,重建镜像耗时较长,对于普通 CentOS 虚拟机,优先尝试 fstrim,不行再离线转换。
问:virt-sparsify 会不会损坏数据?
正常执行不会损坏数据,但任何改写磁盘元数据的行为都有风险,建议在操作前复制原 qcow2 文件备份,或者至少确认文件系统已 umount,对缺少经验的新手来说,它远比直接用 qemu-img 安全,但对生产环境仍然建议先做快照。
CentOS 虚拟机清理后空间不释放,本质上就是文件系统、LVM 和虚拟化镜像三层之间的“空间翻译”出现了延迟,删文件只是第一步,真正让空间回到宿主机,还要靠 fstrim、lvreduce 和镜像重建这一套组合拳。