WSL / WSL 2 をコマンドラインでインストールする

## はじめに

Windows 10 の環境が増えてきたので備忘録。何度も同じことをするとなると、やっぱコマンドラインの方が、記述するのも、実行するのも楽だと思う。

手順の流れとしては GUI でやることと変わらないが、Microsoftストアに接続しなくても良い、所属ドメインのポリシで色々と制限されている環境でも利用できる、というのが大きなメリット。WSL 2 がサポートされている Windows 10 であれば、WSL 1 での動作を確認した後でも WSL 2 に移行することができるし、さらに WSL 1 に戻ることもできる。

## 試した環境

- Windows 10 Professional もしくは Enterprise version 1803 (Redstone 4）, 1809（Redstone 5）, 1903（19H1）, 20H2, 21H1
- PC, VMware Fusion, Parallels Desktop

## 手順

### 1. WSL のインストール

**管理者権限の PowerShell**（Windows のスタートボタンを右クリックして起動するのが楽） で

```PowerShell
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
```

を実行し、リブートする。


### 2. ディストロのダウンロード

ディストロパッケージの好みのものを好みの手段でダウンロードする。最近の Windows 10 で、かつ、ダウンロードしたパッケージを保存しておく必要がなければ、`wsl.exe` をいきなり起動する方法 3b. もある。

最新のディストロパッケージ一覧は[Microsoftのオンラインマニュアル](https://docs.microsoft.com/en-us/windows/wsl/install-manual#downloading-distributions)に記載されている。
- Ubuntu 22.04 (https://aka.ms/wslubuntu2204)
- Ubuntu 20.04 (https://aka.ms/wslubuntu2004)
- Ubuntu 18.04 (https://aka.ms/wsl-ubuntu-1804)
- Ubuntu 16.04 (https://aka.ms/wsl-ubuntu-1604)
- Debian GNU/Linux (https://aka.ms/wsl-debian-gnulinux)
- Kali Linux (https://aka.ms/wsl-kali-linux)
- OpenSUSE 42 (https://aka.ms/wsl-opensuse-42)
- OpenSUSE Leap 15.2 (https://aka.ms/wsl-opensuseleap15-2)
- SLES 12 (https://aka.ms/wsl-sles-12)
- SLES 15 SP2 (https://aka.ms/wsl-SUSELinuxEnterpriseServer15SP2)
- Oracle Linux 8.5 (https://aka.ms/wsl-oraclelinux-8-5)
- Fedora Remix for WSL (https://github.com/WhitewaterFoundry/WSLFedoraRemix/releases/)

ディトロのパッケージは Windows 10 に同梱されるようになった `curl.exe` でダウンロードする。指定した URL からリダイレクトされるため `-L` を忘れないように。Ubuntu 20.04 LTS のパッケージのダウンロードは次の通り。

```PowerShell
curl.exe -L https://aka.ms/wslubuntu2004 -o ~\Downloads\Ubuntu2004.appx
```

なお、`curl` が `Invoke-WebRequest` の別名として定義されているが、`curl` や `Invoke-WebRequest` でダウンロードすると非常に時間がかかるので、注意が必要。

### 3. ディストロのインストールと初期化

**管理者権限の PowerShell** で以下を実行する。

```PowerShell
Add-AppxPackage ~\Downloads\Ubuntu2004.appx
```

インストールに成功すれば、スタートメニューにディストロの名前があるはず。Windows Update が動作中の場合はインストールに失敗するので、もしそれが原因の場合には終了後に再度インストールを実行すると成功するだろう。そうでない場合の対策は 3a. で。

あとは通常通り。スタートメニューのディストロ名をクリックすると、ディストロの初期化が始まる。

### 3a. ディストロのインストールや初期化に失敗する場合

次の手順で任意の場所にインストールできる（**管理者権限は不要**）。

1. ダウンロードしたディストロパッケージの拡張子を `appx` から `zip` に変更する
2. その zip ファイルを自分の好きなフォルダ（例えば、`~\AppData\Local\Packages\ディストロ名` など）に展開する
3. 展開したフォルダに `cd` し、そこにある exe ファイルを実行する
4. ディストロの初期化に成功すれば、Unixユーザ名を聞いてくるので適当なユーザ名（Windowsのログイン名でも良いが、異なっても問題なし）とパスワードを設定する
5. （optional）上記の exe ファイルをスタートにピン留めする
6. （optional）同じフォルダにある `install.tar.gz` を消去する

```PowerShell
cd ~\Downloads
Rename-Item Ubuntu2004.appx Ubuntu2004.zip
Expand-Archive Ubuntu2004.zip ~\AppData\Local\Packages\Ubuntu-20.04
cd ~\AppData\Local\Packages\Ubuntu-20.04
.\ubuntu2004.exe
```

ディストロのインストールや初期化に失敗する原因は色々あるようだが、以上の手順でもダメな場合には、あきらめた方がよさそう。

### 3b. ディストロのダウンロードとインストールをまるっと実行

最近の Windows 10 であれば、`wsl.exe` コマンドによって色々とまとめて実行することができる（**管理者権限は不要**）。

```PowerShell
wsl --list --online
```

とすると、インストールできるディストロ名の一覧が表示されるので、ディストロ名を指定して、

```PowerShell
wsl --install -d ディストロ名
```

とすると、ディストロのダウンロード、インストール、初期化、スタートメニューへの登録までやってくれる。この場合、ディストロのイメージは `~\AppData\Local\Packages` の下に展開される。

### 4. WSL 2 への移行

WSL 2 を試してみよう。

まず、**管理者権限の PowerShell** で以下を実行し、リブートする。なお、VMware や Parallels などの仮想環境上で Windows を動かしている場合には、リブートではなく Windows のシャットダウンを実行し、nested virtualization（仮想環境上でハイパバイザを動かせるモード）をオンにして、Windows を起動する。

```PowerShell
Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform
```

次に、**通常の権限で PowerShell を起動**し、ディストロ名を確認し、WSL 2 へ移行したいディストロの WSL バージョンを 2 に設定すると、WSL 1 から WSL 2 へディストロイメージが変換される。この時、「アップデートが必要」というようなメッセージが出て、変換が途中で止まる場合には、指示にしたがってアップデートを実施する。指示を見逃した場合には、https://aka.ms/wsl2kernel を見ると良い。

```
PS> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         1
PS> wsl --set-version Ubuntu-20.04 2
Conversion in progress, this may take a few minutes...
For information on key differences with WSL 2 please visit https://aka.ms/wsl2
Conversion complete.
PS> wsl -l -v
  NAME            STATE           VERSION
* Ubuntu-20.04    Stopped         2
```

あとは、いつもと同じように WSL を起動すれば良い。

WSL 1 に戻る場合は `wsl --set-version ディストロ名 1` を実行すれば良い。また、アンインストールは下記の 5. または 5a. でできる。

#### WSL と Linux カーネルのアップデート

次に、WSL と WSL 用の Linux カーネルを最新版にアップデートする。**管理者権限の PowerShell** で以下を実行する。

```PowerShell
wsl --shutdown
wsl --update
```

shutdown と update の順序は逆でも大丈夫。

最近は ``wsl --update`` とすると、Microsoft Store へ接続しにいくが、組織のポリシなどで Microsoft Store への接続が禁止されている場合には、管理者権限で ``wsl --update --web-download`` とすれば良い。例えば、こんな感じ。

```
PS> wsl --update --web-download
ダウンロード中: Linux 用 Windows サブシステム
インストール中: Linux 用 Windows サブシステム
Linux 用 Windows サブシステム  はインストールされました。
PS> wsl --version
WSL バージョン: 1.2.5.0
カーネル バージョン: 5.15.90.1
WSLg バージョン: 1.0.51
MSRDC バージョン: 1.2.3770
Direct3D バージョン: 1.608.2-61064218
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows バージョン: 10.0.19045.3324
```


### 5. ディストロのアンインストール

上記の 3. でインストールした場合は、**管理者権限の PowerShell** で以下を実行する。これで、ユーザごとに初期化した（展開された）ディストロも全て消去される。

```PowerShell
Get-AppxPackage *ubuntu20* | Remove-AppxPackage -AllUsers -Confirm
```

### 5a. ディストロのアンインストール

上記の 3a. でインストールした場合は、wsl もしくは wslconfig で unregister してから、ディストロを展開したフォルダごと消去する。

```PowerShell
wsl --unregister Ubuntu-20.04
Remove-Item ~\AppData\Local\Packages\Ubuntu2004 -Recurse
```

### 5b. ディストロのアンインストール

上記の 3b. でインストールした場合は、今のところ `wsl --uninstall` というオプションはないので、次のような手順になる。

```PowerShell
Get-AppxPackage *ubuntu20* | Remove-AppxPackage -Confirm
```

## おわりに

コマンドラインだけで WSL 2 を使えるようになったのは良いのだが、ネットワーク周りが WSL 1 と様子がだいぶ異なったり、仮想マシン上の Windows で WSL 2 を使うと、[Windows との時間のずれが気になったり](https://qiita.com/moriai/items/f633e01728d8d062adb1)と、WSL 1 ベースでファイル I/O を効率化するぐらいで良かったのではとも思ったりもするが。