Find and delete unattached Azure managed and unmanaged disks by using Azure PowerShell

Applies to: ✔️ Linux VMs ✔️ Windows VMs ✔️ Flexible scale sets ✔️ Uniform scale sets

When you delete a virtual machine (VM) in Azure, by default, any disks that are attached to the VM aren't deleted. This feature helps to prevent data loss due to the unintentional deletion of VMs. After a VM is deleted, you will continue to pay for unattached disks. This article shows you how to find and delete any unattached disks and reduce unnecessary costs.

Note

You can use the Get-AzureDisk command to get the LastOwnershipUpdateTime for any disk. This property represents when the disk’s state was last updated. For an unattached disk, this shows the time when the disk was unattached. This property is blank for newly created disks, until their state changes.

Managed disks: Find and delete unattached disks

The following script looks for unattached managed disks by examining the value of the ManagedBy property. When a managed disk is attached to a VM, the ManagedBy property contains the resource ID of the VM. When a managed disk is unattached, the ManagedBy property is null. The script examines all the managed disks in an Azure subscription. When the script locates a managed disk with the ManagedBy property set to null, the script determines that the disk is unattached.

Important

First, run the script by setting the deleteUnattachedDisks variable to 0. This action lets you find and view all the unattached managed disks.

After you review all the unattached disks, run the script again and set the deleteUnattachedDisks variable to 1. This action lets you delete all the unattached managed disks.

# Set deleteUnattachedDisks=1 if you want to delete unattached Managed Disks
# Set deleteUnattachedDisks=0 if you want to see the Id of the unattached Managed Disks
$deleteUnattachedDisks=0
$managedDisks = Get-AzDisk
foreach ($md in $managedDisks) {
    # ManagedBy property stores the Id of the VM to which Managed Disk is attached to
    # If ManagedBy property is $null then it means that the Managed Disk is not attached to a VM
    if($md.ManagedBy -eq $null){
        if($deleteUnattachedDisks -eq 1){
            Write-Host "Deleting unattached Managed Disk with Id: $($md.Id)"
            $md | Remove-AzDisk -Force
            Write-Host "Deleted unattached Managed Disk with Id: $($md.Id) "
        }else{
            $md.Id
        }
    }
 }

Unmanaged disks: Find and delete unattached disks

Unmanaged disks are VHD files that are stored as page blobs in Azure storage accounts. The following script looks for unattached unmanaged disks (page blobs) by examining the value of the LeaseStatus property. When an unmanaged disk is attached to a VM, the LeaseStatus property is set to Locked. When an unmanaged disk is unattached, the LeaseStatus property is set to Unlocked. The script examines all the unmanaged disks in all the Azure storage accounts in an Azure subscription. When the script locates an unmanaged disk with a LeaseStatus property set to Unlocked, the script determines that the disk is unattached.

Important

First, run the script by setting the deleteUnattachedVHDs variable to $false. This action lets you find and view all the unattached unmanaged VHDs.

After you review all the unattached disks, run the script again and set the deleteUnattachedVHDs variable to $true. This action lets you delete all the unattached unmanaged VHDs.

# Set deleteUnattachedVHDs=$true if you want to delete unattached VHDs
# Set deleteUnattachedVHDs=$false if you want to see the Uri of the unattached VHDs
$deleteUnattachedVHDs=$false
$storageAccounts = Get-AzStorageAccount
foreach($storageAccount in $storageAccounts){
    $storageKey = (Get-AzStorageAccountKey -ResourceGroupName $storageAccount.ResourceGroupName -Name $storageAccount.StorageAccountName)[0].Value
    $context = New-AzStorageContext -StorageAccountName $storageAccount.StorageAccountName -StorageAccountKey $storageKey
    $containers = Get-AzStorageContainer -Context $context
    foreach($container in $containers){
        $blobs = Get-AzStorageBlob -Container $container.Name -Context $context
        #Fetch all the Page blobs with extension .vhd as only Page blobs can be attached as disk to Azure VMs
        $blobs | Where-Object {$_.BlobType -eq 'PageBlob' -and $_.Name.EndsWith('.vhd')} | ForEach-Object { 
            #If a Page blob is not attached as disk then LeaseStatus will be unlocked
            if($_.ICloudBlob.Properties.LeaseStatus -eq 'Unlocked'){
                    if($deleteUnattachedVHDs){
                        Write-Host "Deleting unattached VHD with Uri: $($_.ICloudBlob.Uri.AbsoluteUri)"
                        $_ | Remove-AzStorageBlob -Force
                        Write-Host "Deleted unattached VHD with Uri: $($_.ICloudBlob.Uri.AbsoluteUri)"
                    }
                    else{
                        $_.ICloudBlob.Uri.AbsoluteUri
                    }
            }
        }
    }
}

Next steps

For more information, see Delete a storage account and Identify Orphaned Disks Using PowerShell