WSL: Gerenciando o disco da distro
Tags: wsl
Published: 2024-06-18 11:00:00

Quando se trabalha com softwares pesados, geralmente é necessária uma quantidade considerável de espaço em disco a fim de armazenar todas as configurações e módulos para sua execução. Com o WSL não é diferente, afinal trata-se de um SO extra instalado na máquina. Para que seja possível realizar a instalação desse novo SO, o Windows cria um HD de tamanho variável (VHDX) no qual conterá todos os arquivos do SO e todos os programas e arquivos instalados posteriormente.

De acordo com a própria [documentação da Microsoft](https://learn.microsoft.com/en-us/windows/wsl/disk-space#how-to-check-your-available-disk-space):
> O tamanho do disco será de 1TB para as versões mais recentes do WSL2 e 512Gb ou 256GB para versões mais antigas.
> O tamanho do disco exibido é seu tamanho máximo, ainda que este espaço não esteja realmente alocado. VHD expandirá seu tamanho a medida do seu uso.

Quando é realizada a instalação do SO no WSL, por padrão o Windows cria o VHD no mesmo HD onde o próprio Windows está instalado (C:). Muitas vezes o tamanho deste disco é insuficiente para comportar um VHD tão grande e em constante expansão.

Utilizando o meu próprio HD como exemplo é possível observar que o disco está quase esgotado:

![O espaço livre no disco atual é de 2.25GB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yyxkhas5okcleggvqv4w.png)

Analisando a alocação do disco nota-se que o SO instalado no WSL ocupa em torno de 25% de espaço:

![O tamanho da distro Ubuntu no WSL ocupa 63.9GB no disco](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k2fp96qnjqia6xlkvufu.png)

Neste post vou abordar duas propostas de como recuperar mais espaço em disco: 
1. Realizando a compactação do disco
2. Movendo a distro para outro HD

## 1. Compactar o disco

Esta opção é indicada para quem utiliza o WSL como servidor para algum container engine (docker, podman) ou para quem manipula muitos arquivos (cria, copia, exclui). Ela é aplicável independente de onde o VHD está salvo.

Para efetuar a compactação do disco é necessário desligar a distro.

```powershell
wsl --shutdown
```

> Obs: esse comando desliga todas as distros. Não é possível utilizar o comando terminate pois ele não libera o VHD para manipulação externa.
> 
> Para reiniciar as distros basta rodar o comando `wsl -d <distro-name>`

Para descobrir quais distros estão instaladas na máquina e seus respectivos status basta rodar o comando:

```powershell
wsl -l -v
```

O resultado será parecido com esse:

```powershell
  NAME                      STATE           VERSION
* Ubuntu                    Stopped         2
  podman-machine-default    Stopped         2
  docker-desktop-data       Stopped         2
```

Em seguida será necessário obter o local onde o VHD está armazenado. Por padrão o Windows adiciona todos os arquivos necessários para rodar a distro dentro de um diretório armazenado na pasta `C:\Users\%USERNAME%\AppData\Local\Packages`. Existem algumas formas de encontrar o diretório da distro:

1. Rodando o comando `(Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq '<distribution-name>' }).GetValue("BasePath") + "\ext4.vhdx"`
2. Acessar a pasta `C:\Users\%USERNAME%\AppData\Local\Packages` e procurar pelo nome do pacote da distro
   1. Para distros Ubuntu os arquivos estão localizados em pastas com o padrão `CanonicalGroupLimited.Ubuntuon*`
3. Usar a pesquisa de arquivos dentro da pasta `C:\Users\%USERNAME%\AppData\Local\Packages` para buscar todos os `ext4.*` disponíveis e validar qual é o caminho que contém o VHD da distro desejada.

> No meu caso a primeira opção não funcionou em nenhuma das duas máquinas das quais testei.
No fim não encontrei uma forma fácil de encontrar os VHD's que são criados por distros instaladas diretamente pela Microsoft Store. Outras VMs criadas por outros programas, como o podman possuem comandos que facilitam a localização do VHD utilizado.

Uma vez encontrado o caminho do VHD será necessário abrir o powershell/terminal em modo administrador e executar o seguinte comando:

```powershell
Optimize-VHD "C:\Users\$env:UserName\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\ext4.vhdx" -Mode Full
```
Explicando:

O comando **Optimize-VHD** serve para otimizar a alocação de espaço em VHDs de tamanho dinâmico, isto é, que expandem seu tamanho no decorrer do uso até o tamanho máximo definido.

A opção **Mode** serve para definir o nível de otimização. No meu caso testei com as opções **Quick** e **Full**. Abaixo explico a diferença de cada uma:

- Quick: desaloca os blocos não usados do disco, porém não procura por zero blocks
- Full: Busca por zero blocks e desaloca blocos não utilizados.

> As demais opções podem ser encontradas documentação oficial(tem nas referências 😉)
  
Rodando o comando com `-Mode Quick` obtive a seguinte redução:
![Otimização com a opção Quick reduziu o tamanho do VHD em 13.2GB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3615f9gpbvntvsuubmar.png)

Rodando o comando com `-Mode Full` obtive a seguinte redução:
![Otimização com a opção Full reduziu o tamanho do VHD em 13.7GB]
(https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6dbv0kb9bbx2h3e81jk2.png)

> Obs: O comando com -Mode Full foi rodado após ter rodado o comando com o -Mode Quick. Esse é o motivo da diferença parecer pequena de um comando para o outro.

Após executar o processo de otimização do VHD o espaço disponível no HD aumentou aproximadamente 14Gb:

![Espaço livre no HD após recuperar blocos não usados pelo VHD foi de 14GB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5m40matg4f0jgq9haaly.png)

### Vantagens da abordagem

1. Poucos passos
2. Manter o registro do SO baixado pela Microsoft Store, beneficiando-se dos clis instalados junto com as distros.
3. Não necessita de armazenamento extra

### Desvantagens da abordagem

1. Inefetivo quando todo espaço reservado pelo VHD está ocupado
2. Dependendo do uso é necessário executar o procedimento com frequência de forma manual ou automatizada
3. Dificuldade de encontrar o caminho do VHD do SO desejado

## 2. Exportar o VHD para outro disco

Esta opção é indicada para cenários onde é necessário ou desejado mover a distro para outro HD com mais capacidade ou reservado para isso.

Ao término da execução desse processo, o espaço ocupado no meu HD principal reduziu consideravelmente.

![HD principal está com 66.2GB de espaço livre. O tamanho ocupado reduziu em 63.95GB](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wdh13c7zb9pq3mmyesg7.png)

### 2.1 Exportar o disco
O primeiro passo é desligar a distro desejada. Esse passo é essencial para garantir que nada esta sendo gravado durante a cópia dos arquivos.

```ps
wsl --terminate <distro-name>
```

> alternativamente o comando `wsl --shutdown` pode ser utilizado para desligar todas as distros

O próximo passo é rodar o comando de exportar:

```powershell
wsl --export <distro-name> <path-destino-com-nome>.vhdx --vhd
```
Explicando:

O comando exporta a distro para o arquivo vhdx indicado. A opção --vhd é opcional, porém será útil para os próximos passos. Caso a opção --vhd não seja informada, um arquivo **.tar** será gerado. Ambos os formatos de arquivo servem para a etapa de import.

### 2.2 Importando e registrando a distro no WSL

> Importante: Nomes repetidos não são permitidos pois os nomes funcionam como o identificador da distro para com o WSL. Portanto, se for necessário manter o nome da distro original, primeiro deve ser feito o desregistro da distro anterior. Nesse caso a ordem de execução fica: 2.3, 2.2, 2.4

Com o disco exportado existem duas formas de importar a distro no WSL:
1. Carregando uma cópia do HD com o comando **import**
2. Utilizando o próprio VHD exportado com o comando **import-in-place** (só funciona para arquivos **.vhdx**)

A primeira forma consiste em rodar o comando import de acordo com o exemplo:

```powershell
wsl --import <distro-name> <path-instalacao-distro> <path-disco-exportado>.vhdx --vhd
```

Explicando:

Este comando restaurará uma cópia do disco exportado no local informado e o registrará a distro no WSL com o nome informado. A opção --vhd serve para informar que o arquivo utilizado é um VHD ao invés de um **.tar**.

A segunda forma de importação só funciona para arquivos do tipo **.vhdx**. Para realizar esse processo basta executar o comando:

```powershell
 wsl --import-in-place <distro-name> <path-disco-exportado>.vhdx
```
Explicando:

Este comando registrará a distro no WSL com o nome informado, utilizando o VHD como o disco daquela distro. Então ao contrário do comando `wsl --import`, esse comando utiliza o vhd diretamente e é por este motivo que a exportação precisa da opção --vhd.

### 2.3 Desregistrando a distro antiga

Com a distro registrada em outro HD, o próximo passo é remover a distro antiga do HD principal. Para desregistrar a distro atual, rodar o comando:

```ps
wsl --unregister <distro-name>
```

Executando o comando acima todas as configurações dessa distro serão removidas do HD principal.

### 2.4 Definindo a distro como padrão e restaurando o usuário principal

Apesar de todo o trabalho feito até o momento existem alguns pontos que precisam ser ajustados quando necessário.

O primeiro deles é definir a distro como padrão rodando o comando:

```ps
wsl --set-default <distro-name>
```

O segundo ajuste é redefinir o usuário principal. Ao exportar a distro e (re)importá-la o usuário padrão é redefinido para root. Para redefinir o usuário para o usuário anteriormente criado na distro será necessário criar o arquivo **wsl.config** dentro da distro contendo a estrutura abaixo

```config
[user]
default=<username>
```

este arquivo deve ser salvo no caminho `/etc/` (lembrar que escrever na pasta etc exige `sudo`). Após salvar o arquivo, reiniciar a máquina utilizando os comandos:

```ps
wsl --terminate <distro-name> #desliga a máquina
```

```ps
wsl -d <distro-name> #inicia a máquina
```

### Vantagens da abordagem

1. Pode ser utilizada para importar qualquer distro, inclusive de outros computadores ou backups
2. Pode ser utilizada junto com o método de Compactação de disco (Optimize-VHD)
3. Libera todo o espaço do VHD do HD principal
4. Não é necessário saber o local físico onde a distro está instalada.
5. Capacidade de utilizar os cli's junto a Microsoft Store caso o nome da distro importada seja igual a distro original

### Desvantagens da abordagem

1. Requer espaço extra em outro HD
2. Necessita ajustes adicionais
3. Perda da capacidade de utilizar as cli's baixadas junto a Microsoft Store caso o nome da distro importada seja diferente da distro original

# Referências

- [Documentação do comando Optimize-VHD](https://learn.microsoft.com/en-us/powershell/module/hyper-v/optimize-vhd?view=windowsserver2022-ps)
- [Como gerenciar o espaço em disco do WSL](https://learn.microsoft.com/en-us/windows/wsl/disk-space)
- [Import export distro](https://winaero.com/export-import-wsl-linux-distro-windows-10/)
- [Definir um usuário padrão na distro](https://superuser.com/a/1627461)
- [wsl.conf - WSL advanced settings](https://learn.microsoft.com/en-us/windows/wsl/wsl-config#user-settings)