You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

读取VM列表转换为Azure托管磁盘时遇PowerShell脚本问题

解决Azure VM转换托管磁盘的PowerShell脚本问题

我来帮你一步步排查和修复这两个核心问题:


问题1:导出CSV时拿到全订阅VM而非指定列表

你的脚本逻辑里犯了一个关键错误:每次读取vm.txt里的一行,就执行一次Get-Azurermvm(拉取全订阅所有VM),然后把所有结果追加到CSV里,自然最终CSV里是全订阅VM的重复数据。

修复方案

先读取txt里的VM信息,再从订阅中精准筛选对应的VM,再导出CSV。假设你的vm.txt每行格式为资源组名 VM名称(比如RG-01 vm-01),代码调整如下:

# 读取txt并整理成结构化的VM列表
$vmList = Get-Content C:\temp\vm.txt | ForEach-Object {
    $parts = $_.Trim().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)
    # 确保每行是有效的资源组+VM名格式
    if ($parts.Count -eq 2) {
        [PSCustomObject]@{
            ResourceGroupName = $parts[0]
            Name = $parts[1]
        }
    }
}

# 筛选指定VM并导出CSV(替换你原来的导出逻辑)
$vmList | ForEach-Object {
    Get-Azurermvm -ResourceGroupName $_.ResourceGroupName -Name $_.Name | Select-Object ResourceGroupName,Name
} | Export-Csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Force

如果你的vm.txt只有VM名称,可改用Where-Object筛选:

$vmNames = Get-Content C:\temp\vm.txt
Get-Azurermvm | Where-Object { $vmNames -contains $_.Name } | Select-Object ResourceGroupName,Name | Export-Csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Force

问题2:循环中参数无法传递给Stop/Convert命令

你的循环语法混合了管道ForEach-Object和常规foreach循环,导致$_变量无法正确指向当前VM对象。

修复方案

选以下两种正确的循环写法之一即可:

方式1:常规foreach循环(用循环变量引用)

$comps = Import-Csv c:\temp\Vm.csv
foreach ($Comp in $comps) {
    Stop-AzureRmVM -ResourceGroupName $Comp.ResourceGroupName -Name $Comp.Name -Force
    ConvertTo-AzureRmVMManagedDisk -ResourceGroupName $Comp.ResourceGroupName -VMName $Comp.Name
}

方式2:管道式ForEach-Object(用$_引用)

Import-Csv c:\temp\Vm.csv | ForEach-Object {
    Stop-AzureRmVM -ResourceGroupName $_.ResourceGroupName -Name $_.Name -Force
    ConvertTo-AzureRmVMManagedDisk -ResourceGroupName $_.ResourceGroupName -VMName $_.Name
}

完整修正后的脚本

整合所有修复点,加上日志提示和订阅切换的规范写法:

# 登录并切换目标订阅
Login-AzureRmAccount
$sub = Get-AzureRmSubscription | Out-GridView -PassThru
Set-AzureRmContext -Subscription $sub.Id

# 从txt读取VM列表并导出正确CSV
$vmList = Get-Content C:\temp\vm.txt | ForEach-Object {
    $parts = $_.Trim().Split(' ', [System.StringSplitOptions]::RemoveEmptyEntries)
    if ($parts.Count -eq 2) {
        [PSCustomObject]@{
            ResourceGroupName = $parts[0]
            Name = $parts[1]
        }
    }
}

$vmList | ForEach-Object {
    Get-Azurermvm -ResourceGroupName $_.ResourceGroupName -Name $_.Name | Select-Object ResourceGroupName,Name
} | Export-Csv c:\temp\vm.csv -NoClobber -NoTypeInformation -Force

# 执行停止VM并转换为托管磁盘
Import-Csv c:\temp\vm.csv | ForEach-Object {
    Write-Host "正在停止VM: $($_.Name)..."
    Stop-AzureRmVM -ResourceGroupName $_.ResourceGroupName -Name $_.Name -Force -ErrorAction Stop
    Write-Host "正在转换VM $($_.Name)为托管磁盘..."
    ConvertTo-AzureRmVMManagedDisk -ResourceGroupName $_.ResourceGroupName -VMName $_.Name -ErrorAction Stop
    Write-Host "VM $($_.Name)转换完成!`n"
}

内容的提问来源于stack exchange,提问作者Norrin Rad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:54:47