如何通过PowerCLI批量删除vSphere孤立VMDK僵尸文件?
PowerCLI批量删除RVTools识别的孤立VMDK操作方案
方案适配说明
- 此前尝试的
Get-VDisk、Remove-HardDisk命令仅支持操作已挂载关联到虚拟机的磁盘对象,未关联任何VM的孤立VMDK不属于vCenter的虚拟机磁盘托管对象,因此会出现参数不识别、操作仅支持挂载到VM的设备这类报错。 - 以下方案全程通过已连接的vCenter Server执行,无需单独登录或指定单台ESXi主机,原生适配RVTools vHealth报告输出的
[DatastoreName] VMfolder/virtualDiskName.vmdk格式路径。 - 强制提醒:正式删除前必须执行干运行校验,确认待删文件列表100%匹配预期,避免误删生产数据
操作流程
- 提前完成vCenter连接:执行
Connect-VIServer -Server 你的vCenter地址,输入具备存储文件操作权限的账号密码完成认证。 - 整理RVTools导出的待删孤立VMDK路径,保存为纯文本文件(例如
orphan_vmdk_list.txt),每行一个路径,格式参考:
[ds-prod-01] old_app_vm/old_app_vm_3.vmdk
[ds-archive-02] 2022_backup/backup_disk_01.vmdk
- 先执行干运行校验脚本,该步骤不会删除任何文件,仅输出所有匹配到的待删文件信息,逐一核对存储位置、文件大小、修改时间是否符合预期:
# 读取待处理路径列表 $vmdkList = Get-Content .\orphan_vmdk_list.txt foreach ($vmdkPath in $vmdkList) { # 解析RVTools输出的路径格式,拆分存储名和文件相对路径 if ($vmdkPath -match '^\[(?<dsName>[^\]]+)\]\s*(?<relPath>.+)$') { $datastoreName = $matches.dsName $fileRelativePath = $matches.relPath # 查找对应数据存储 $targetDS = Get-Datastore -Name $datastoreName -ErrorAction SilentlyContinue if (-not $targetDS) { Write-Warning "跳过 $vmdkPath:未找到名称为 $datastoreName 的数据存储" continue } # 通过vCenter API挂载存储为PSDrive,无需连接ESXi主机 $dsDrive = New-PSDrive -Location $targetDS -Name "TempDS_$datastoreName" -PSProvider VimDatastore -Root "\" -ErrorAction SilentlyContinue if (-not $dsDrive) { Write-Warning "跳过 $vmdkPath:无法挂载数据存储 $datastoreName 为临时驱动器" continue } # 查找目标VMDK文件 $targetFile = Get-Item -Path "TempDS_$datastoreName:\$fileRelativePath" -ErrorAction SilentlyContinue if (-not $targetFile) { Write-Warning "跳过 $vmdkPath:对应路径下未找到文件" Remove-PSDrive -Name $dsDrive.Name -Force -ErrorAction SilentlyContinue continue } # 输出文件校验信息 Write-Host "匹配到待删文件:路径 $vmdkPath | 大小 $([math]::Round($targetFile.Length/1GB,2))GB | 最后修改时间 $($targetFile.LastWriteTime)" # 清理临时驱动器 Remove-PSDrive -Name $dsDrive.Name -Force -ErrorAction SilentlyContinue } else { Write-Warning "跳过 $vmdkPath:路径格式不符合RVTools输出规范" } }
- 干运行核对无误后,执行正式删除脚本,脚本会自动清理VMDK关联的flat、delta、ctk等附属文件,无需单独处理:
# 读取待处理路径列表 $vmdkList = Get-Content .\orphan_vmdk_list.txt foreach ($vmdkPath in $vmdkList) { if ($vmdkPath -match '^\[(?<dsName>[^\]]+)\]\s*(?<relPath>.+)$') { $datastoreName = $matches.dsName $fileRelativePath = $matches.relPath $targetDS = Get-Datastore -Name $datastoreName -ErrorAction SilentlyContinue if (-not $targetDS) { Write-Warning "跳过 $vmdkPath:未找到名称为 $datastoreName 的数据存储" continue } $dsDrive = New-PSDrive -Location $targetDS -Name "TempDS_$datastoreName" -PSProvider VimDatastore -Root "\" -ErrorAction SilentlyContinue if (-not $dsDrive) { Write-Warning "跳过 $vmdkPath:无法挂载数据存储 $datastoreName 为临时驱动器" continue } $targetFile = Get-Item -Path "TempDS_$datastoreName:\$fileRelativePath" -ErrorAction SilentlyContinue if (-not $targetFile) { Write-Warning "跳过 $vmdkPath:对应路径下未找到文件" Remove-PSDrive -Name $dsDrive.Name -Force -ErrorAction SilentlyContinue continue } # 执行删除操作 Remove-Item -Path "TempDS_$datastoreName:\$fileRelativePath" -Force -ErrorAction SilentlyContinue if ($?) { Write-Host "删除成功:$vmdkPath" } else { Write-Error "删除失败:$vmdkPath,错误信息:$($error[0].Exception.Message)" } Remove-PSDrive -Name $dsDrive.Name -Force -ErrorAction SilentlyContinue } else { Write-Warning "跳过 $vmdkPath:路径格式不符合RVTools输出规范" } }
常见问题处理
- 若删除时报权限错误,给当前vCenter连接账号分配对应数据存储的「低级别文件操作」「删除文件」权限即可。
- 若提示VMDK被占用无法删除,回到RVTools检查该磁盘是否确实未关联任何VM,部分快照关联的磁盘会被判定为孤立但实际被快照引用,这类文件不要删除。
- 脚本执行过程中创建的临时PSDrive会在每次循环结束自动清理,不会残留到PowerCLI会话中。
内容的提问来源于stack exchange,提问作者Roman
相关产品推荐
相关产品推荐

