我在 Windows 10 上的 WSL2 上使用 Ubuntu 20.04,我注意到在 Ubuntu 上删除文件后,我没有恢复被删除文件占用的空间。例如:在我删除 Ubuntu 上的文件之前,Windows 资源管理器显示我在 ( C:
) 驱动器上的可用空间约为 46GB。然后,在我删除了大约 10GB 的文件(在我的情况下是一些临时的 Gatsby 网站)后,可用空间甚至更少,大约 45GB,我觉得这非常奇怪。
那么我该如何恢复那些未使用的位?是否有一些我可以使用终端命令,或者我可以通过 Windows GUI 等执行某些操作?
答案1
2023 年 9 月更新:据报道,WSL(2.0.0)的新预版本为磁盘映像提供了一种新的“稀疏”模式,当删除文件时,该模式会自动缩小映像。
虽然我还没有亲自测试过,但从DevBlog公告,您可以使用以下命令从 PowerShell 将现有磁盘映像转换为稀疏磁盘映像:
wsl --manage <distro> --set-sparse true
您还可以将以下内容添加到您的.wslconfig
(位于 Windows轮廓目录(而不是 WSL 内部)以使任何新创建的发行版映像都是稀疏的:
[experimental]
sparseVhd=true
较早的答案:
有一个 WSL Github问题就此话题展开讨论。WSL 将自动增大虚拟磁盘 (ext4.vhdx),但缩小虚拟磁盘以回收未使用的空间目前必须手动完成。
您需要做的第一件事是了解 ext4.vhdx 的位置。对于默认的 Ubuntu 安装,它应该位于类似%USERPROFILE%\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\
然后,您可以使用几种技术来删除未使用的空间。我建议您从开始wsl --shutdown
并复制 vhdx 作为备份以开始。如果您正在运行 Docker Desktop,也请将其关闭,否则它可能会在您之后无意中尝试重新启动 WSL --shutdown
。
如果你使用的是 Windows Professional 或更高版本,则可以安装 Hyper-V 并使用 Optimize-VHD 命令行,如原始问题。 。
在 Windows Home (及更高版本)上,您可以
diskpart
按照说明使用在这条评论中。导出 WSL 发行版并将其重新导入到新的 WSL 实例中(例如此评论)也将回收空间。请注意,导入后需要重置默认用户名。请参阅这里(和这里以寻找替代选择)。
我已经亲自测试并确认了第二种和第三种技术。
答案2
optimize-vhd
当您的系统中没有let 命令时,请执行以下操作:
在管理磁盘之前关闭 wsl
wsl --shutdown
将以下脚本保存为 compact-disk.txt
select vdisk file="C:\Users\%username%\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04onWindows_79rhkp1fndgsc\LocalState\ext4.vhdx"
attach vdisk readonly
compact vdisk
detach vdisk
以管理员身份打开提示并运行上面保存的脚本
diskpart /s <SAVED_SCRIPT_FOLDER_PATH>\compact-disk.txt
答案3
- 在 Windows 功能中激活 Hyper-V 模块(控制面板 -> 打开或关闭 Windows 功能 -> 激活 Hyper-v -> 重新启动)。这是激活 optimize-vhd 命令所必需的。
- 以管理员身份打开 Windows Powershell:首先,按 Windows+R 打开运行,然后在文本框中输入“powershell”。接下来,按 Ctrl+Shift+Enter。Windows PowerShell 将以管理员模式打开。在 Powershell 中,运行以下命令。
wsl.exe --shutdown
- cd 进入 ext4.vhdx 文件夹,通常是
cd C:\Users\<user>\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu20.04onWindows_79rhkp1fndgsc\LocalState\
optimize-vhd -Path .\ext4.vhdx -Mode full
(确保 ext4.vhdx 没有被鼠标点击,因为这会导致 powershell 中出现该文件正在被另一个进程使用的错误)
答案4
使用此自动提升脚本,您可以一次压缩多个 vhdx。
# Self-elevate the script if required
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
#Full Path of vhdx file
$d1 = #Ex: "E:\Docker\wsl\data\ext4.vhdx"
$d2 = ""
$d3 = ""
$d4 = ""
$d5 = ""
$d6 = ""
$paths = $d1, $d2, $d3, $d4, $d5, $d6
foreach ($file in $paths) {
echo ""
echo "Befor Shrinking File sizes in MB"
Get-ChildItem -Path $file | Select-Object FullName, @{Name = "Size"; E = { $_.Length / 1MB } }
echo ""
echo "---------"
echo "Shrinking $file"
echo "---------"
wsl --shutdown
Optimize-VHD -Path $file -Mode Full
echo ""
echo "After Shrinking File sizes in MB"
Get-ChildItem -Path $file | Select-Object FullName, @{Name = "Size"; E = { $_.Length / 1MB } }
echo ""
echo ""
echo ""
echo ""
}
Read-Host -Prompt "Press Enter to exit"
顺便说一句,通过一些调整,你也可以在启动时运行它(应该禁用“登录时启动 Docker”)。