获取AzureRM托管磁盘空间使用与剩余空间——PowerShell技术求助
这个问题我碰到过好多次——Azure的控制平面能轻松拿到托管磁盘的元数据(比如容量、系统类型这些),但磁盘的已用/可用空间属于VM内部操作系统层面的信息,Azure本身不会主动收集这些数据。所以要拿到这两个值,必须从运行中的VM内部去获取。下面给你两种可行的方案,结合你已有的脚本实现完整需求:
核心原理说明
Azure的Get-AzDisk只能获取磁盘的物理属性(比如容量、ID、关联VM等),而文件系统的使用情况是OS内部的状态,只有通过远程执行命令、自定义脚本扩展等方式进入VM内部才能拿到。
方案1:通过PowerShell远程直接获取(适合少量VM)
这个方案适合VM数量不多的场景,直接远程连接到VM执行命令,把磁盘使用数据和你已有的基础信息合并。
完整脚本示例
# 初始化结果数组 $diskReport = @() # 获取所有Azure VM $allVMs = Get-AzVM foreach ($vm in $allVMs) { $vmName = $vm.Name $rgName = $vm.ResourceGroupName $osType = $vm.StorageProfile.OsDisk.OsType # 获取VM关联的所有托管磁盘(OS盘+数据盘) $vmDisks = Get-AzDisk | Where-Object { $_.Id -eq $vm.StorageProfile.OsDisk.ManagedDisk.Id -or $vm.StorageProfile.DataDisks.ManagedDisk.Id -contains $_.Id } foreach ($disk in $vmDisks) { # 先收集基础磁盘信息 $diskInfo = [PSCustomObject]@{ VMName = $vmName DiskName = $disk.Name CapacityGB = $disk.DiskSizeGB OSType = $osType ResourceGroupName = $rgName UsedSpaceGB = $null FreeSpaceGB = $null } # 根据OS类型远程获取磁盘使用情况 try { if ($osType -eq "Windows") { # Windows VM:用Invoke-Command远程执行卷查询 $volumeData = Invoke-Command -ComputerName $vm.PrivateIpAddress ` -Credential (Get-Credential) ` -ScriptBlock { Get-Volume | Where-Object { $_.DriveType -eq 'Fixed' } | Select-Object DriveLetter, Size, SizeRemaining } # 关联磁盘和卷:OS盘默认匹配C:,数据盘根据LUN或盘符调整 if ($disk.Id -eq $vm.StorageProfile.OsDisk.ManagedDisk.Id) { $osVolume = $volumeData | Where-Object { $_.DriveLetter -eq 'C:' } $diskInfo.UsedSpaceGB = [math]::Round(($osVolume.Size - $osVolume.SizeRemaining)/1GB, 2) $diskInfo.FreeSpaceGB = [math]::Round($osVolume.SizeRemaining/1GB, 2) } else { # 数据盘可根据实际盘符/LUN匹配,这里简化取第一个非C:固定卷 $dataVolume = $volumeData | Where-Object { $_.DriveLetter -ne 'C:' } | Select-Object -First 1 if ($dataVolume) { $diskInfo.UsedSpaceGB = [math]::Round(($dataVolume.Size - $dataVolume.SizeRemaining)/1GB, 2) $diskInfo.FreeSpaceGB = [math]::Round($dataVolume.SizeRemaining/1GB, 2) } } } elseif ($osType -eq "Linux") { # Linux VM:用Invoke-AzVMRunCommand执行shell命令 $runResult = Invoke-AzVMRunCommand -ResourceGroupName $rgName ` -VMName $vmName ` -CommandId 'RunShellScript' ` -ScriptString "df -h --output=source,size,used,avail | grep -v tmpfs | grep -v devtmpfs" # 解析磁盘挂载信息 $outputLines = $runResult.Value[0].Message -split "`n" | Where-Object { $_ -match '/dev/' } $diskLun = ($vm.StorageProfile.DataDisks | Where-Object { $_.ManagedDisk.Id -eq $disk.Id }).Lun foreach ($line in $outputLines) { $parts = $line -split '\s+' | Where-Object { $_ } $device = $parts[0] $usedGB = [double]($parts[2] -replace 'G','') $freeGB = [double]($parts[3] -replace 'G','') # 关联磁盘:OS盘匹配/dev/sda类设备,数据盘根据LUN匹配(LUN0对应/dev/sdb,以此类推) if ($disk.Id -eq $vm.StorageProfile.OsDisk.ManagedDisk.Id -and $device -match 'sda') { $diskInfo.UsedSpaceGB = [math]::Round($usedGB, 2) $diskInfo.FreeSpaceGB = [math]::Round($freeGB, 2) } elseif ($diskLun -ne $null) { $expectedDevice = "/dev/sd$(char([int][char]'b' + $diskLun))" if ($device -eq $expectedDevice) { $diskInfo.UsedSpaceGB = [math]::Round($usedGB, 2) $diskInfo.FreeSpaceGB = [math]::Round($freeGB, 2) } } } } } catch { Write-Warning "无法获取VM $vmName 的磁盘使用数据:$_" } $diskReport += $diskInfo } } # 输出最终报表 $diskReport | Format-Table VMName, DiskName, CapacityGB, OSType, ResourceGroupName, UsedSpaceGB, FreeSpaceGB -AutoSize
方案2:用自定义脚本扩展批量收集(适合大量VM)
如果你的VM数量很多,逐个远程连接效率太低,可以用Azure自定义脚本扩展批量在VM上运行收集脚本,把数据统一存储到Azure存储账户,再后续合并分析。
步骤示例
创建收集磁盘使用情况的脚本(分Windows/Linux):
- Windows脚本(
Collect-DiskUsage.ps1):$diskData = Get-Volume | Where-Object { $_.DriveType -eq 'Fixed' } | Select-Object @{Name='VMName';Expression={$env:COMPUTERNAME}}, DriveLetter, @{Name='CapacityGB';Expression={[math]::Round($_.Size/1GB,2)}}, @{Name='UsedSpaceGB';Expression={[math]::Round(($_.Size - $_.SizeRemaining)/1GB,2)}}, @{Name='FreeSpaceGB';Expression={[math]::Round($_.SizeRemaining/1GB,2)}} $diskData | ConvertTo-Json | Out-File "C:\DiskUsage.json" # 上传到存储账户 $storageContext = New-AzStorageContext -StorageAccountName "your-storage-account" -StorageAccountKey "your-storage-key" Set-AzStorageBlobContent -File "C:\DiskUsage.json" -Container "disk-usage" -Blob "$env:COMPUTERNAME-DiskUsage.json" -Context $storageContext - Linux脚本(
collect-disk-usage.sh):VM_NAME=$(hostname) df -h --output=source,size,used,avail | grep -v tmpfs | grep -v devtmpfs | awk -v vm="$VM_NAME" '{print "{\"VMName\":\""vm"\",\"Device\":\""$1"\",\"CapacityGB\":\""$2"\",\"UsedSpaceGB\":\""$3"\",\"FreeSpaceGB\":\""$4"\"}"}' > /tmp/disk-usage.json # 上传到存储账户(需要安装azcopy或azure-cli) az storage blob upload --account-name your-storage-account --account-key your-storage-key --container-name disk-usage --file /tmp/disk-usage.json --name "$VM_NAME-disk-usage.json"
- Windows脚本(
将脚本上传到Azure存储容器,然后批量部署自定义脚本扩展到所有VM:
$storageAccount = Get-AzStorageAccount -ResourceGroupName "your-rg" -Name "your-storage-account" $allVMs = Get-AzVM foreach ($vm in $allVMs) { if ($vm.StorageProfile.OsDisk.OsType -eq "Windows") { Set-AzVMCustomScriptExtension -ResourceGroupName $vm.ResourceGroupName ` -VMName $vm.Name ` -Name "CollectDiskUsage" ` -StorageAccountName $storageAccount.StorageAccountName ` -StorageAccountKey $storageAccount.Context.StorageAccountKey ` -ContainerName "scripts" ` -FileName "Collect-DiskUsage.ps1" ` -Run "Collect-DiskUsage.ps1" } else { Set-AzVMCustomScriptExtension -ResourceGroupName $vm.ResourceGroupName ` -VMName $vm.Name ` -Name "CollectDiskUsage" ` -StorageAccountName $storageAccount.StorageAccountName ` -StorageAccountKey $storageAccount.Context.StorageAccountKey ` -ContainerName "scripts" ` -FileName "collect-disk-usage.sh" ` -Run "collect-disk-usage.sh" } }从存储账户下载所有json文件,解析后和
Get-AzDisk获取的基础信息合并即可。
关键注意事项
- VM必须处于运行状态,否则无法远程连接或执行脚本扩展。
- 网络安全组(NSG)需要开放对应端口:Windows开放5985/5986(WinRM),Linux开放22(SSH)。
- 远程连接需要VM的本地管理员/root权限,或者配置了Azure AD身份验证的权限。
- 磁盘与卷/设备的关联逻辑可能需要根据你的实际环境调整(比如Linux的NVMe磁盘设备名是
/dev/nvme*而不是/dev/sd*)。
内容的提问来源于stack exchange,提问作者Norrin Rad
相关产品推荐
相关产品推荐

