﻿# 如何將 Hyper-V 底下的 Linux 虛擬機器使用的 VHDX 虛擬硬碟進行壓縮處理

公司有一台佔用將近 500GB 的 Linux 虛擬機器，經詢問工程師後發現，這台虛擬機器之所以會佔用這麼多空間，主要是因為在測試部署的時候，都沒有將先前部署過後的檔案刪除，導致額外浪費許多磁碟空間，增加備份的成本。但是當我用 Hyper-V 的**編輯磁碟**功能嘗試壓縮 VHDX 虛擬硬碟時，卻發現佔用的磁碟空間無法釋放，原來還有一道工序沒有執行導致。今天這篇文章就來說說這個作法。

![Hyper-V 編輯磁碟](https://stwillblogassets.blob.core.windows.net/files/images/external/user-images.githubusercontent.com/ff90ec5767e058c3d185-195889261-a0aad03c-b215-47f7-bf69-b285af6584f7.png)

基本上，要壓縮 Hyper-V 虛擬磁碟(VHDX)有以下幾點步驟要做：

1.  確認你的 VHDX 是**動態擴充虛擬硬碟**(Dynamically expanding virtual hard disk)，否則將無法壓縮！
    
2.  刪除作業系統中無用的檔案，騰出磁碟空間！
    
    你可以透過 `cd /; sudo du -h --max-depth=1` 找出系統中最占空間的根目錄第一層資料夾，藉此找到所有可能殘留暫存檔案的地方，並設法安全的刪除這些檔案。
    
3.  理解 `Empty blocks` (空磁區) 與 `Unused blocks` (未使用磁區) 的差異
    
    因為 VHDX 壓縮的原理，將磁碟中的**空磁區**(`Empty`)刪掉而已，但大部分檔案系統在刪除檔案時，其實只是將檔案所在的位置從 allocation table 標注刪除而已，事實上資料並沒有真的刪除，所以這些曾經建立過的檔案雖然刪除了，但其實資料還在硬碟裡，這些只是**未使用磁區**(`Unused blocks`)而已，所以其實還是佔著磁碟空間，Hyper-V 的「編輯磁碟」功能並無法將 `Unused blocks` 的空間清出來。
    
4.  執行 `sudo df -h` 命令，查看目前系統中的檔案系統有哪些
    
    ```
    Filesystem                         Size  Used Avail Use% Mounted on
    udev                                16G     0   16G   0% /dev
    tmpfs                              3.2G  964K  3.2G   1% /run
    /dev/mapper/ubuntu--vg-ubuntu--lv  448G  176G  253G  41% /
    tmpfs                               16G     0   16G   0% /dev/shm
    tmpfs                              5.0M     0  5.0M   0% /run/lock
    tmpfs                               16G     0   16G   0% /sys/fs/cgroup
    /dev/sda2                          974M  205M  702M  23% /boot
    /dev/loop0                         128K  128K     0 100% /snap/bare/5
    /dev/loop1                         144M  144M     0 100% /snap/chromium/2117
    /dev/loop2                         143M  143M     0 100% /snap/chromium/2105
    /dev/loop3                          56M   56M     0 100% /snap/core18/2560
    /dev/loop4                          56M   56M     0 100% /snap/core18/2566
    /dev/loop5                          62M   62M     0 100% /snap/core20/1611
    /dev/loop7                         165M  165M     0 100% /snap/gnome-3-28-1804/161
    /dev/loop6                          64M   64M     0 100% /snap/core20/1623
    /dev/loop8                         347M  347M     0 100% /snap/gnome-3-38-2004/115
    /dev/sda1                          511M  5.3M  506M   2% /boot/efi
    /dev/loop9                          68M   68M     0 100% /snap/lxd/22526
    /dev/loop10                         48M   48M     0 100% /snap/snapd/17029
    /dev/loop11                         68M   68M     0 100% /snap/lxd/22753
    /dev/loop12                         92M   92M     0 100% /snap/gtk-common-themes/1535
    /dev/loop13                         48M   48M     0 100% /snap/snapd/16778
    /dev/loop14                        347M  347M     0 100% /snap/gnome-3-38-2004/119
    /dev/loop15                         82M   82M     0 100% /snap/gtk-common-themes/1534
    tmpfs                              3.2G     0  3.2G   0% /run/user/1002
    ```
    
5.  執行 `sudo fstrim /` 將所有 `Unused blocks` 清空，轉變成真正的 `Empty blocks`
    
    由於 `fstrim` 執行速度超快，我的 448GB 磁碟大約只要 10 秒左右就可以完成清理動作。
    
6.  使用 Hyper-V 的「編輯磁碟」功能壓縮 VHDX 虛擬硬碟
    
    我的這台 VM 在執行完 `fstrim /` 之後，磁碟空間多騰出了 150GB 左右，真是太棒了！👍
    

### 相關連結

-   [How to Compact a VHDX with a Linux Filesystem](https://www.altaro.com/hyper-v/compact-vhdx-linux-filesystem/)
-   [How to Shrink a WSL2 Virtual Disk](https://stephenreescarter.net/how-to-shrink-a-wsl2-virtual-disk/)
