如何合并具有多个差异磁盘的检查点

适用于: Windows Server 2022、Windows Server 2019、Windows Server 2016

介绍

本文介绍在 Hyper-V 生成了许多差异磁盘时可用于将检查点合并到虚拟机(VM)的方法。 使用的方法取决于情况的详细信息。

合并可在 Hyper-V 管理器中查看的检查点

可以在 Hyper-V 管理器中查看的检查点是最简单的处理点。 通常,可以使用上下文菜单上的 “删除检查点” 命令删除这些检查点。

Hyper-V 管理器中检查点的屏幕截图,其中上下文菜单包含“删除检查点”命令。

在某些情况下,“删除检查点”和“删除检查点子树”不会显示在上下文菜单上。 如果第三方备份软件生成检查点,但在备份操作后不会删除它们,则可能会出现这种情况。

在这些情况下,仍可以使用 Delete 密钥删除检查点。

总之,若要删除 Hyper-V 管理器中的检查点(并合并差异磁盘文件),请执行以下步骤:

  1. 在 Hyper-V 管理器,选择虚拟机。
  2. 检查点 列表中,右键单击要删除的检查点,然后执行以下操作之一:
    • 选择“ 删除检查点”。
    • 如果 “删除检查点 ”不可用,请选择检查点,然后选择“ Del”。

合并无法在 Hyper-V 管理器中查看的检查点

可能会遇到 Hyper-V 管理器不显示特定 VM 的检查点的情况。 同时,相应的文件系统文件夹显示许多差异磁盘文件。 如果第三方备份软件生成检查点,但在备份操作后不会删除它们,则可能会出现这种情况。

可以通过以下两种方式之一合并差异磁盘文件,具体取决于是否可以关闭 VM。

何时可以关闭 VM

若要合并差异磁盘文件,请关闭 VM。 通常,差异磁盘文件合并为 VM 关闭过程的一部分。

无法关闭 VM 时

可以将差异磁盘合并到联机 VM。 但是,这是一个涉及 Windows PowerShell 脚本的多步骤过程。 为此,请遵循以下常规步骤:

  1. 备份所有差异磁盘文件(VHD 文件)。
  2. 创建并运行 Get-VHDChain 函数。 本部分后面将详细介绍此步骤。
  3. 创建并运行合并命令。 本部分后面将详细介绍此步骤。
  4. 将 VM 设置更改为指向合并的父 VHD。
  5. 启动 VM。 成功的启动意味着合并已成功完成。

创建并运行 Get-VHDChain 函数

  1. 在 Hyper-V 主机服务器上,打开管理 PowerShell 命令提示符窗口。

  2. 复制以下脚本,然后将其粘贴到 PowerShell 窗口中:

    function Get-VHDChain {
        [CmdletBinding()]
        param(
            [string]$ComputerName = $env:COMPUTERNAME,
            [string[]]$Name = '*'
        )
        try {
            $VMs = Get-VM -ComputerName $ComputerName -Name $Name -ErrorAction Stop
        }
        catch {
            Write-Warning $_.Exception.Message
        }
        foreach ($vm in $VMs){
            $VHDs = ($vm).harddrives.path
            foreach ($vhd in $VHDs){
                Clear-Variable VHDType -ErrorAction SilentlyContinue
                try {
                    $VHDInfo = $vhd | Get-VHD -ComputerName $ComputerName -ErrorAction Stop
                }
                catch {
                    $VHDType = 'Error'
                    $VHDPath = $vhd
                    Write-Verbose $_.Exception.Message
                }
                $i = 1
                $problem = $false
                while (($VHDInfo.parentpath -or $i -eq 1) -and (-not($problem))){
                    If ($VHDType -ne 'Error' -and $i -gt 1){
                        try {
                            $VHDInfo = $VHDInfo.ParentPath | Get-VHD -ComputerName $ComputerName -ErrorAction Stop
                        }
                        catch {
                            $VHDType = 'Error'
                            $VHDPath = $VHDInfo.parentpath
                            Write-Verbose $_.Exception.Message
                        }
                    }
                    if ($VHDType -ne 'Error'){
                        $VHDType = $VHDInfo.VhdType
                        $VHDPath = $VHDInfo.path
                    }
                    else {
                        $problem = $true
                    }
                    [pscustomobject]@{
                        Name = $vm.name
                        VHDNumber = $i
                        VHDType = $VHDType
                        VHD = $VHDPath
                    }
                    $i++
                }
            }
        }
    }
    ==================================
    

    此脚本定义一个 Get-VHDChain 函数,用于标识 VHD 链(VM 的不同磁盘集)。

  3. 运行以下命令:

    Get-vhdchain -name <virtual machine name>
    

    注意

    在此命令中, <虚拟机名称> 表示虚拟机的名称。

    运行脚本时,应会看到类似于以下输出的输出。

    Get-VHDChain 脚本的输出的屏幕截图。

  4. 确保 Get-VHDChain 运行时不会出现错误。

    重要

    Get-VHDChain如果输出包含错误,则必须从文件夹中删除受影响的差异磁盘。 在以下示例中,Disk 24 生成了错误,并且必须从不同的磁盘文件夹中删除。

    脚本生成错误时 Get-VHDChain 脚本的输出的屏幕截图。

创建并运行合并命令

  1. 以下说明在 C:\temp\merge.txt 中创建脚本以合并磁盘。 执行以下步骤:

    1. 在本地 C: 驱动器上,创建名为 temp 的文件夹。

    2. 打开管理 PowerShell 窗口,然后运行以下命令:

      $vm = Read-Host("please enter the VMname") 
      
    3. 在命令提示符处,输入虚拟机名称。

    4. 复制以下脚本,然后将其粘贴到命令提示符处。

      $vhds=Get-VM $vm | Select-Object -Property VMId | Get-VHD 
      if (Test-Path '.\merge.txt'){Remove-Item -Path '.\merge.txt'}
      foreach($vhd in $vhds){
      $chain=[ordered]@{}
          while ($vhd.ParentPath){
              $chain.add($vhd.Path,$vhd.ParentPath)
              $vhd=Get-VHD -Path $vhd.ParentPath
              }
      $chain.GetEnumerator() | ForEach-Object {
          $line='Merge-VHD -Path "{0}" -Destination "{1}"' -f $_.key, $_.value
          $line | Out-File -FilePath .\merge.txt  -Append
          }    
      }
      

      该脚本应类似于以下脚本:

      将脚本粘贴到 PowerShell 窗口中后的屏幕截图。

  2. 打开 C:\temp\merge.txt。 此文件包含一个命令行命令列表,这些命令行命令分组成对。 每个命令对定义单个差异磁盘的合并操作。

  3. 复制第一对的第一个命令,将其粘贴到命令提示符处,然后运行它。 然后,对第一对的第二个命令执行相同的操作。 这些操作合并命令地址的不同磁盘。

  4. 在磁盘合并后,对列表中的下一个差异磁盘重复上述步骤。 对于merge.txt文件地址的所有差异磁盘,请继续操作。