VHDs auslesen mit PowerShell: Größe, Speicherort, Typ, Fragmentierung

    VHD und VDHX mit Hyper-VDie x86-Virtualisierung erlaubt das Anlegen von virtuellen Maschi­nen mit wenigen Mausklicks. Entsprechend schnell vermehrt sich in vielen Umgebungen die Zahl der virtuellen Laufwerke. PowerShell kann helfen, den Überblick über die vorhandenen VHD(X)-Dateien zu bewahren.

    Ein unkontrolliertes Wachstum von VMs stellt unter anderem ein Storage-Problem dar, wenn die virtuellen Maschinen nicht mehr genutzt werden, aber ihre Laufwerke weiterhin Platz belegen. Besonders schwer sind solche Platzverschwender zu entdecken, wenn VHD(X)-Dateien verwaist sind, also zu keiner VM mehr gehören (siehe dazu: Nicht verwendete VHDs in Hyper-V finden mit PowerShell).

    Liste von VHDs abrufen

    Auch unabhängig von solchen Zombie-VHDs ist es interessant zu wissen, wie viele VHDs die Speichersysteme bevölkern, wie viel Platz sie belegen und über welche Verzeichnisse sie verstreut sind.

    Für die meisten Abfragen benötigt man erst eine Liste aller VHD(X). Diese könnte man natürlich bekommen, indem man die Standardverzeichnisse für Hyper-V mit Get-ChildItem ausliest. Aber nachdem gerade auch VHDs an unerwarteten Orten entdeckt werden sollen, empfiehlt sich der Einsatz von Cmdlets aus dem Modul Hyper-V, die ihre Daten aus der VM-Konfiguration extrahieren.

    Nachdem man die Liste mit den VHDs in einer Variablen gespeichert hat, kann man alle möglichen Informationen abrufen.

    Dazu gibt man im ersten Schritt folgenden Befehl ein:

    $VHDs = Get-VM | select VMID | Get-VHD

    Er ermittelt mit Get-VM alle VMs auf dem aktuellen Host (einen Remote-Host könnte man über den Parameter -ComputerName angeben) und ruft anhand ihrer IDs mit Get-VHD die Liste der ihnen zugeordneten virtuellen Laufwerke ab. Der Befehl

    ($VHDs).count

    informiert anschließend darüber, wie viele (A)VHD(X)-Dateien insgesamt gefunden wurden.

    VHD-Verzeichnisse anzeigen

    Will man nun wissen, ob sich VMs entgegen der Best Practices für Hyper-V noch im Standardverzeichnis (also auf dem Systemlaufwerk im Profil des Users Public) befinden, dann kann man dies auf folgende Weise überprüfen:

    $VHDs | ? Path -like "C:\Users\Public\*" | select Path

    Dieses Kommando verwendet das Alias "?" für Where-Object, um Tipparbeit zu sparen. Es gibt den vollständigen Pfad inklusive Dateiname für alle VHD(X) aus, die sich unterhalb von C:\Users\Public befinden.

    Möchte man eine Übersicht über alle Verzeichnisse bekommen, in denen sich virtuelle Laufwerke befinden, dann hilft dieser Aufruf:

    ($VHDs | select path).path -replace "[^\\]*\.a?vhdx?","" | sort -Uniq

    Die Ergebnisse dürften auf vielen Rechnern einige Überraschungen bergen, besonders dann, wenn man die Import- und Exportfunktion für VMs häufig nutzt.

    Die Eigenschaft Path enthält auch den Dateinamen der VHD(X), den man aber nicht gebrauchen kann, wenn man nur eine Liste der Verzeichnisse haben möchte. Der reguläre Ausdruck nach dem replace-Operator entfernt ihn deshalb. Der Aufruf von sort -uniq eliminiert Dubletten, so dass jeder Pfad nur einmal in der Liste vorkommt.

    Platzverbrauch von VHDs berechnen

    Eine sicher interessante Information ist jene über den Platzverbrauch der virtuellen Laufwerke. Möchte man wissen, wie viele GB von den VHD(X) insgesamt belegt werden, dann lässt sich das mit

    $VHDs | %{$FS += $_.FileSize}; $FS/1GB

    herausfinden. Dieser Befehl iteriert über alle Elemente von $VHDs, summiert die Dateigrößen der einzelnen virtuellen Laufwerke in der Variablen $FS auf und rechnet sie schließlich in GB um.

    Will man die Abfrage auf jene VHD(X) reduzieren, die inaktiven VMs zugeordnet sind und daher aktuell nicht verwendet werden, dann modifiziert man den Aufruf folgendermaßen:

    $VHDs | ? Attached -eq $false | %{$FS += $_.FileSize}; $FS/1GB

    Verwendet man die Variable $FS nachfolgend in weiteren Befehlen, dann ist daran zu denken, dass man sie vorher durch

    $FS = 0

    zurücksetzt.

    VHDs nach Größe sortieren

    Eine Übersicht über die größten Verbraucher von Speicherplatz erhält man, wenn man die Liste der VHD(X) nach Größe sortiert anzeigt:

    $VHDs | sort -Des -Prop FileSize | select Path, @{Name="GByte";Expression={$_.FileSize/1GB}}

    VHD von VHDX unterscheiden

    Das Cmdlet Get-VHD liefert noch weitere Daten über virtuelle Laufwerke, die man sich zunutze machen kann. So möchte man vielleicht wissen, welche VMs noch VHDs anstatt des neueren und leistungsfähigeren VHDX-Formats verwenden. Dies ließe sich zwar auch über die Dateiendung herausfinden, aber diese Methode ist zuverlässiger:

    $VHDs | ? VHDFormat -eq "VHD"

    Dynamische, fixe oder differenzielle VHD?

    Eine weitere aufschlussreiche Information ist der VHD-Typ. Wenn man etwa VMs von einer Testumgebung auf produktive Systeme übernommen hat und dort nur VHDs fester Größe verwenden will, dann kann man sich anzeigen lassen, ob auf die Konvertierung einzelner Laufwerke vergessen wurde:

    $VHDs | ? VhdType -eq "Dynamic"| Select Path

    Fragmentierung analysieren

    Schließlich informiert eine dafür vorgesehene Eigenschaft über den Grad der Fragmentierung von VHDs, so dass man Hinweise darauf bekommt, wo eine Defragmentierung erforderlich ist:

    $VHDs | select Path, FragmentationPercentage | Out-GridView

    Dieser Aufruf schickt die Ausgabe an das Cmdlet Out-GridView, das die Daten in einer Tabelle auf der grafischen Oberfläche anzeigt und sie damit besser konsumierbar macht. Wenn das Komprimieren von VHD(X) notwendig sein sollte, dann findet sich die zuständige Funktion im Hyper-V Manager unter Datenträger bearbeiten.

    Keine Kommentare