
前几天帮同事处理了一台虚拟机的快照恢复失败报错弹窗很直接但解决过程却是一波三折。这台虚拟机跑着企业内部的一个 MySQL 数据库快照是前一天晚上打的早上想恢复到升级前的状态结果 VMware Workstation 直接给了一个深红色的错误框内容大概是“无法恢复快照”。作为刚接触 VMware 快照的新手我当时第一反应是虚拟机是不是已经废了差点直接喊他重装系统。后来冷静下来才意识到快照恢复失败这件事远没有表面上那么简单。它可能是磁盘空间不足可能是快照链中的增量文件损坏也可能是 .vmsd 元数据出问题甚至只是某个锁文件没释放。这篇内容不是官方文档的复述而是我实际踩过坑之后整理的笔记。如果你刚开始接触 VMware 快照或者在某个维护窗口里遇到过“恢复失败”的弹窗那这篇应该能帮你省下半天排查时间。这篇内容主要讲三件事快照恢复的原理和失败的本质如何通过日志、文件结构定位问题以及从命令行手动恢复快照的完整操作流程。我也会把常见的报错信息和实际处理方案做成速查表方便你以后遇到类似问题时直接对照。1. 快照恢复失败是怎么回事先搞懂快照的底层逻辑1.1 快照不是备份是“时光指针”很多新手第一次用 VMware 快照时会把它理解成“备份”。这个理解最大的问题是快照一旦损坏你仍然什么都救不回来。快照的本质是一个指向虚拟机磁盘某个时间点的“指针”它靠一整套依赖关系来工作。虚拟机正常运行时所有写入操作都直接落在磁盘文件上。你打了一个快照之后VMware 会把当前磁盘状态“冻结”成只读的父磁盘后续虚拟机的新增写入全部进入一个新建的增量磁盘文件也就是我们常说的-delta.vmdk。每打一次快照就会多出一层这样的增量文件形成一条快照链。如果把这个结构用生活里的东西类比它更像游戏里的存档系统。基础磁盘是游戏本体的初始状态每次快照就是一个存档点存档之后你在游戏里做的所有操作都会记录在一个新的“进度文件”里。你想回到某个存档只需要丢弃后面的进度文件即可。但问题是如果其中一个进度文件损坏了恢复流程就会直接卡住。所以快照恢复失败本质上不是“某一个文件坏了”而是“整条依赖链”出了问题。你在 GUI 上点一下“恢复”VMware 要做的事情远比表面看起来复杂它要校验快照链上的每个节点、检查元数据文件、确认目标快照是否可达还要预留足够的空间来切换磁盘状态。任何一个环节出问题都会导致恢复操作失败。1.2 恢复失败的本质增量链断了或脏数据挡住了路我排查这个案例时最直观的感受是“恢复失败”其实是一类问题的统称。它不一定代表你的数据丢了更多时候只是 VMware 无法安全地完成快照切换宁可报错也不继续执行。常见的故障模型有这么几类第一增量链断裂。某个-delta.vmdk文件头损坏、文件大小异常或者磁盘描述符指向了一个不存在的父盘恢复时 VMware 无法拼出完整的时间线。这是最棘手的情况因为不仅无法恢复快照还可能导致当前虚拟机也无法启动。第二元数据损坏。.vmsd文件保存了快照树的信息包括快照名称、 UUID、对应磁盘文件路径。如果.vmsd里某个快照条目指向了不存在的文件或者格式被写坏GUI 上可能仍然能看到快照列表但一点“恢复”就会报错。第三环境因素。磁盘空间不足、文件被锁、虚拟机电源状态异常这些看起来跟快照无关的问题也会让恢复操作失败。比如虚拟机还处于运行状态时强行点恢复VMware 需要先做一次硬重置如果宿主机的 IO 卡顿或者虚拟机的系统正在执行大量写操作恢复过程就很容易超时。理解了这个底层逻辑后再回头看那次“理直气壮”的失败就会发现其实每个报错都有迹可循。2. 那次恢复失败的全过程复盘2.1 现场情况一个“理直气壮”的失败说回同事那台虚拟机。宿主机是 Windows 10VMware Workstation Pro 17虚拟机是 Ubuntu Server。前一天晚上打了一个快照名字起得很朴素叫“before-upgrade”。早上他准备升级某个组件担心出问题所以先尝试恢复快照打算确认一下能否正常回滚。结果点击“恢复”之后窗口直接卡了十几秒然后弹出了报错。具体信息我记得不太清了大意是“无法恢复到快照 before-upgrade因为一个磁盘文件被锁定或无效”。这个报错在论坛上很常见但新手的典型反应会是快照是我自己打的文件路径也没动过为什么会锁定是不是虚拟机废了复盘这一步的重点是不要被报错文案吓住而是先去“还原现场”。我当时注意到虚拟机处于挂起状态不是关机也不是运行。同事之前为了省电点了“挂起客户机”然后再尝试恢复快照。快照恢复操作在挂起状态下不是不能做但如果虚拟机的内存状态文件.vmsn和当前的快照链不一致恢复过程就会非常容易卡住。那么现场的判断结论是不要急着重装虚拟机也不要对着 GUI 反复点“恢复”。先关闭 VMware 对这台虚拟机的所有占用再检查文件系统层面的状态。2.2 排查第一步看虚拟机文件目录里发生了什么关掉 VMware Workstation 之后我打开了虚拟机所在的目录。这里提一下虚拟机目录下常见的文件有这些CentOS7.vmx虚拟机配置CentOS7.vmdk和CentOS7-flat.vmdk原始磁盘描述文件和实际数据文件CentOS7-000001.vmdk和CentOS7-000001-delta.vmdk第一个快照对应的描述文件和增量文件CentOS7-000002.vmdk和CentOS7-000002-delta.vmdk第二个快照对应的文件CentOS7.vmsd快照树元数据CentOS7.vmsn挂起状态或快照的内存状态文件vmware.logVMware 运行日志只看一眼文件列表就能发现不少线索。我注意到CentOS7-000002-delta.vmdk的大小是 0创建时间正好是今天凌晨强制关机的时间点。而正常情况下一个有内容的 delta 文件大小至少是几 MB。一个 0 大小的 delta 文件说明两个问题要么虚拟机在这个快照之后几乎没写入过数据要么这个增量文件根本没被正确初始化。再把CentOS7.vmsd用记事本打开可以看到快照树的结构。里面记录的快照 UUID、磁盘键值等信息对应关系一目了然。如果你发现某个快照条目引用的磁盘文件是CentOS7-000002.vmdk但实际文件不存在这就是恢复失败的直接原因。检查文件时我记得很清楚那个 0 字节的 delta 文件后面对应的父级描述文件也出现了异常这说明快照链里已经有节点损坏了。到这个阶段问题范围基本锁定不是空间不足也不是锁冲突而是增量链上的某个节点损坏。2.3 用 vmware.log 定位真正原因检查文件结构能看出“哪里不正常”但要搞清楚“为什么不正常”必须看日志。在 Windows 宿主机上虚拟机目录下的vmware.log是文本文件可以直接打开搜索关键词。我习惯先搜snapshot再搜error和fail。如果日志太多可以用 findstr 过滤findstr /i snapshot error fail vmware.logLinux 宿主机上对应的是grep -i snapshot\|error\|fail vmware.log日志里最关键的信息是恢复快照操作开始时的记录。当时我们看到了一段类似这样的内容DISKLIB-LINK: Opened disk CentOS7-000002.vmdk (ranges) DISKLIB-LINK: CentOS7-000002.vmdk is not a disk.这句话的意思是VMware 按照快照链打开CentOS7-000002.vmdk时发现这个文件并不是一个合法的磁盘描述文件于是整个恢复操作中止。后面紧跟着一条Disk chain is broken的记录。看到这里“为什么报错”已经有了明确答案CentOS7-000002.vmdk文件头损坏导致快照链无法闭合。再往前翻日志发现凌晨有一次虚拟机强制关机很可能就是在那个节点写入中断留下了坏文件。到这里我建议所有遇到快照恢复失败的人第一件事永远是打开日志而不是凭感觉重装。日志里记录的不仅仅是报错还包括操作前虚拟机的状态、文件锁、磁盘查找路径这些信息能直接帮你跳过大量无用尝试。3. 恢复失败常见原因与判断方法3.1 磁盘空间不足最常见的“隐形杀手”恢复快照时VMware 不是简单地把虚拟机“切”到另一个文件而是需要做一系列合并和重写操作。比如删除中间快照时需要把增量数据合并到父磁盘恢复到某个快照时又需要调整当前磁盘链的引用关系。这个过程中宿主机必须有足够的可用空间否则操作会在某个写入环节失败。按照 VMware 官方的建议恢复操作前宿主机剩余空间最好大于虚拟机所有 vmdk 文件大小总和并保留至少 20% 的余量。我自己的习惯是不管剩余空间多少先跑一次磁盘空间检查。Windows 上用资源管理器看剩余空间Linux 上用df -h。还有一种容易被忽略的情况虚拟机的增量文件在 D 盘但 VMX 配置里的日志或临时文件指向了 C 盘比如 VM 目录下的.lck文件和临时文件默认就在虚拟机目录所在盘。如果 C 盘空间爆掉即使 D 盘空间充足恢复操作同样会失败。判断方法很简单看当前虚拟机目录所在分区的剩余空间再看所有 vmdk 文件的总大小。如果剩余空间仅仅是总大小的一两倍而你的快照链又特别长建议先不要直接点恢复而是先扩展宿主机磁盘或者清理掉一些无用文件否则很容易恢复到一半失败导致更糟糕的连锁问题。3.2 增量磁盘文件损坏链断裂增量磁盘文件损坏是这次踩坑的核心原因。它一般不是突然发生的而是某个异常事件破坏了写入过程。常见的成因有打快照后没有正常关机直接在宿主机层面强制断电VMware Workstation 崩溃后虚拟机进程被强杀宿主机的磁盘出现坏道导致 delta 文件部分扇区读不出来杀毒软件实时扫描锁住了 vmdk 文件写入被中断判断 delta 文件是否损坏可以从文件大小和时间戳入手。一个健康的 delta 文件应该大于 0并且文件头能正常被 VMware 识别。如果你在虚拟机目录里看到某个-delta.vmdk大小骤减、创建时间异常或者在vmware.log里看到is not a disk这类记录那基本可以判定是文件损坏。更正规的检查方式是用 VMware 自带的vmware-vdiskmanager工具。它的完整路径通常是这样C:\Program Files (x86)\VMware\VMware Workstation\vmware-vdiskmanager.exe先查看帮助vmware-vdiskmanager.exe -h然后尝试对可疑的磁盘文件做一次检查。命令格式大致如下vmware-vdiskmanager.exe -R D:\VMs\CentOS7\CentOS7-000002.vmdk需要说明的是-R参数主要用于检查并修复磁盘链的引用关系它不一定能修复所有坏块但能帮你确认“这个文件到底还是不是一个合法的 vmdk”。如果工具返回错误说明这个文件已经不可靠了后面就不要指望它还能正常参与快照链。3.3 版本与快照兼容性问题快照链是严格依赖版本机制的。高版本 VMware 创建的快照拿到低版本里打开经常会出现兼容性提示并且恢复操作可能直接失败。Workstation 和 ESXi 之间的快照结构也有差异虽然都是 vmdk但底层格式和处理方式并不完全一致。我见过一个案例虚拟机原本在 Workstation 17 里创建并打了快照后来用迁移工具导入 ESXi没有提前删除快照结果在 vSphere Client 里恢复快照时一直报错。因为 Workstation 的增量文件格式和 ESXi 的不是很一致强行跨平台操作就遇到了问题。避免这种问题的方法很简单跨大版本升级 VMware 之前先删除所有快照需要从 Workstation 迁移到 ESXi 时导出前先做一次“删除快照”或克隆为独立磁盘如果虚拟机已经存在多层快照并且要迁移最好先把快照链合并干净这个操作在 GUI 里就是“快照管理器 - 删除全部快照”在命令行里可以用vmrun deleteSnapshot逐个清理。不要嫌麻烦快照链太长迁移或升级时的失败概率是指数级上升的。3.4 文件占用与锁冲突快照恢复失败另一个很隐蔽的原因是锁冲突。虚拟机的磁盘文件有一个锁机制当 .vmx 被 VMware 进程打开时同目录下会生成一个.lck目录用来标记磁盘被占用。如果虚拟机没有正常退出而是 VMware Workstation 崩溃了这个.lck目录可能残留下来导致后续所有磁盘操作都被拒绝。判断是否存在锁冲突的方法打开任务管理器搜索vmware-vmx.exe看是否还有残留进程进入虚拟机目录看是否存在.lck目录比如CentOS7.vmdk.lck确认没有虚拟机进程后可以手动删除.lck目录这里要特别提醒删除.lck目录是最后手段必须在确认没有 VMware 进程占用该虚拟机的前提下进行。否则会把正在运行的虚拟机磁盘锁直接扯掉数据损坏风险极高。正确顺序是先在 GUI 里正常关机如果 GUI 已经打不开就用vmrun list查看正在运行的虚拟机再用vmrun stop强制停止最后再考虑删除锁目录。4. 实操从命令行手动恢复快照的完整流程4.1 准备工作备份与状态确认在正式动手之前必须先做三件事。第一备份现场。无论采用什么恢复方案操作前都要把虚拟机的.vmx、.vmsd、所有.vmdk描述文件复制一份出来。如果磁盘空间允许直接复制整个虚拟机目录最好。这一步的核心目的是保证“即使操作失败也不会因为你手贱把现场弄得更糟”。第二确认当前电源状态。用vmrun工具查看虚拟机是否在运行vmrun list这个命令会列出所有正在运行的虚拟机。如果列表里有这台虚拟机先用硬停止命令关闭vmrun stop D:\VMs\CentOS7\CentOS7.vmx hard如果虚拟机是挂起状态可以用vmrun start D:\VMs\CentOS7\CentOS7.vmx先把它正常启动一次再关机目的是刷新快照状态让 VMware 重新识别磁盘链。第三确认恢复目标。这里要用快照管理器里的命名来核对不要凭记忆。我更习惯在 GUI 里打开“快照管理器”截图保存因为命令行里恢复错快照的后果很严重。如果你不确定哪个快照是要恢复的目标宁可多花两分钟看看.vmsd文件里的记录。4.2 合并增量磁盘文件如果目标是删除某个快照而不是回到某个时间点vmrun提供了deleteSnapshot命令它会把目标快照的增量数据合并到父磁盘或子磁盘中。命令格式vmrun deleteSnapshot D:\VMs\CentOS7\CentOS7.vmx before-upgrade注意deleteSnapshot删除的是一个快照节点不会改变虚拟机当前运行状态。如果你有连续三个快照 A、B、C删除中间的快照 B那么 B 的数据会被合并到 A 或 C当前状态保持不变。这是相对安全的操作。但如果你的目标是恢复快照并且你不确定快照链是否完整先尝试用revertToSnapshotvmrun revertToSnapshot D:\VMs\CentOS7\CentOS7.vmx before-upgrade这个命令的作用是让虚拟机回到目标快照的状态等价于 GUI 里的“恢复快照”。如果这条命令能成功那就不用做更复杂的手动合并了。当时我们的情况是revertToSnapshot也失败因为链上那个 0 字节的 delta 文件已经被破坏。这时候我选择不去修复损坏节点而是直接把快照链“拆散”让虚拟机不依赖损坏的增量文件。具体做法是在.vmx文件中找到磁盘配置比如scsi0:0.fileName CentOS7-000002.vmdk把它改成你想要保留的某个磁盘文件比如CentOS7-000001.vmdk然后用这个改过的 vmx 启动虚拟机。这样这台虚拟机就变成了一个独立于原快照链的新虚拟机不再依赖损坏的 delta 文件。这个方法有两个代价第一改 vmx 之后虚拟机文件系统里看到的磁盘就是当时那个快照的状态快照之后的改动全部丢失第二这条操作会让原 vmx 里的旧快照全部失效。所以一定要提前备份原始 vmx并且只在你确实能接受丢失快照之后的变动时才使用。4.3 修复 .vmsd/.vmsn 元数据如果你遇到的是快照树元数据损坏情况会比增量文件损坏温柔一些。.vmsd文件是文本格式里面记录了快照的基本信息包括 uid、displayName、文件名等。如果某个快照条目指向的文件不存在恢复时就会失败但快照链本身可能是完整的。修复的方法是先备份.vmsd然后用文本编辑器打开找到损坏条目的snapshot块整体删除。保存之后重新打开虚拟机快照管理器里就不再有那个坏条目了。注意删掉条目之后对应的 delta 文件会变成“孤儿磁盘”它占用的空间不会自动释放需要手动删除。.vmsn文件的处理要更谨慎。.vmsn保存的是虚拟机的内存状态对应用户说的“挂起时快照”。如果.vmsn损坏恢复时会因为无法读取内存状态而失败。一个可行的办法是把.vmsn文件改名备份比如改成.vmsn.bak这样 VMware 会认为没有挂起状态恢复操作就只处理磁盘数据不再尝试加载内存。代价是恢复之后虚拟机无法回到挂起那一刻的界面状态但对大多数业务场景来说数据恢复比界面状态重要得多。4.4 恢复成功后的检查清单无论你用了哪种方式把虚拟机恢复到可用状态重启之后都不能直接判断“搞定了”。我习惯按这个顺序检查系统是否能正常启动到登录界面磁盘挂载是否正常用df -h确认根分区和业务分区大小数据库或关键服务是否起来比如 MySQL 用systemctl status mysql查看查一下系统日志确认没有大面积的 IO 错误检查快照管理器确认残留的快照链已经被清理干净。不要忽视第五步。很多人在恢复成功后马上投入业务使用却忘了旧快照还在持续占用磁盘空间。快照链不清理后续每次虚拟机写入都会继续积累增量时间长了又会遇到同样的空间问题。5. 常见问题排查速查表与避坑建议5.1 报错信息对照表这段时间我整理了一张常用对照表覆盖了我见过的高频报错。遇到问题时先按表格里的顺序排查通常能省不少事。报错或现象可能原因优先排查方向Cannot revert to snapshot / operation timed out虚拟机电源状态异常、宿主 IO 卡顿先强制关机确认无进程占用后重试No space left on device宿主机磁盘空间不足检查虚拟机目录所在分区剩余空间The file is already in use虚拟机进程残留或锁文件未释放查 vmware-vmx.exe 进程确认后清理 .lckInvalid disk chain / is not a diskdelta 文件损坏用 vmware-vdiskmanager 检查必要时脱离快照链Snapshot metadata is corrupted.vmsd 文件损坏备份后编辑 .vmsd删除坏条目Unable to open parent disk快照链中父级磁盘被移动或删除核对 .vmdk 描述文件中的 CID 引用关系注意表格里的方向只是“优先排查项”不是“唯一答案”。如果按方向排查完仍然没有解决最好立刻打开 vmware.log 搜索关键字日志里的记录远比报错弹窗可靠。5.2 新手最容易踩的三个坑第一个坑是把快照当成备份。这个问题我说了很多次但每次快照恢复失败都会再印证一遍。快照依赖原始 vmdk 和所有增量文件任何一个环节损坏你都无法通过快照找回数据。重要数据必须另外用备份工具做完整备份比如把数据库 dump 出来或者定期把虚拟机导出成 OVA。第二个坑是看到报错就急着重装或者反复点恢复按钮。反复操作不会让损坏的 delta 文件自愈只会增加磁盘 IO 压力。正确做法是停止操作备份现场看日志再动手做恢复。我当时处理同事那台虚拟机时最庆幸的就是没有因为紧张而去重装系统否则数据库数据真的就丢光了。第三个坑是随意删除.lck锁目录。很多教程会说“删掉 .lck 就能解决”但那是针对进程已退出的情况。如果恰好还有另一个 vmware-vmx.exe 在占用这个虚拟机强行删锁会导致磁盘写入错乱比原来的问题更致命。删除之前至少要看一眼任务管理器。5.3 防御型习惯让恢复失败少一点说到底最好的解决方法是让问题不发生。我现在做虚拟机维护已经形成了几个固定习惯。快照链深度保持在 3 层以内。每次打快照前先删除不用的旧快照。快照链越长恢复时需要校验的节点越多失败概率也越大。特别是在做重大系统升级之前宁可先合并旧快照再打一个干净的“升级前快照”。重要操作前同时准备两个快照一个在干净关机状态打一个在业务停止后的运行状态打。这样做的好处是一旦升级过程中系统无法启动你还可以从关机状态快照启动而业务运行状态快照可以在必要时保留故障现场用于分析。跨版本升级 VMware Workstation 或迁移虚拟机之前先清理快照。这一步可以和版本兼容性检查合并在一起。尤其在从 Workstation 转到 ESXi 这类跨平台操作前快照链不清理干净后续的恢复失败几乎是必然结果。6. 写在最后一点个人心得那次快照恢复失败处理完同事问了我一句话“VMware 快照是不是不可靠”我的看法是快照本身是一个可靠的功能但它不是万能的它依赖的是一整套文件系统、磁盘空间和进程状态。任何一个前提被打破恢复就可能失败。关键在于失败之后不要慌先备份再排查最后再动手。我个人在实际操作中现在最重视的其实不是“怎么恢复”而是“尽量别走到需要恢复那一步”。定期清快照、重要数据做外部备份、重大变更前先在测试机演练一遍这些看起来不起眼的习惯反而让我后面几乎没再遇到快照链断裂这种场面。如果你已经读到这里说明你也正在处理快照恢复相关的麻烦。最后再分享一个小技巧处理快照问题时尽量用命令行工具vmrun和vmware-vdiskmanager不要只停留在 GUI 上。GUI 给报错时往往只告诉你“失败了”命令行工具却能让你看到每一步的具体行为排错效率至少翻一倍。