WSL2環境構築 個人用メモ（2021年9月版）

（追記 2023-03-25）Windows10 / Windows11両方で[WSLg](https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/gui-apps)が使えるようになり、X11を使うハードルが激下がりしたので当時頑張って書いた「WSL2側とWindows側でのclipboardの共有」の手順は大幅にカット出来ると思います。

WSL周りは現在進行系で開発が進んでおり、検索しても古い情報が入り混じったりして意外と混乱する（気がする）。

今回、改めてWSL2の環境構築をし直す機会があったので自分用にメモ。
特に、以下の点にフォーカスしている:

- 同一ディストリビューションの環境を複数所有、切り替え
- WSL2側とWindows側でのclipboardの共有
    - X11([VcXsrv](https://sourceforge.net/projects/vcxsrv/))を使うパターン
    - X11を使わずに何とかする([win32yank](https://github.com/equalsraf/win32yank)などを使う)パターン
- ターミナルUIの整備（特にWindows Terminalを使うパターン）


**※注意**

- WSLそのもののインストールの話はあまり書いてなくて、どちらかというとインストールした後の細々とした話が中心です
- あと力尽きて参照リンク貼って終わりみたいなところも多いです（所詮自分用メモなので）
- 時間経つと状況はすぐ変わると思うのでご注意ください。（Windows Insider Programでは[WSLg](https://github.com/microsoft/wslg)などが出ていたりしますし。←正式版が待ち遠しいですね。）

# 0. 実行環境

- Windows10Pro バージョン21H1(OSビルド 19043.1165)
    - `winver`で確認出来る
- 入れたディストリビューション: Ubuntu(20.04)
    - Windowsストアでは`Ubuntu`と`Ubuntu20.04LTS`が独立に存在する（どちらも執筆時点では20.04LTS）
    - どうでも良いが今回は前者の方を使って作業

# 1. WSL2のインストール

[公式ガイド](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10)などを参考に入れる。（[手動インストールの手順](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#manual-installation-steps)を順次実行していく）

とりあえずUbuntuあたりをインストールする

※今回WSL自体は入っている状態から作業しているのでこの辺の記憶は曖昧。。。ここが詳しく知りたい人は別の記事を漁ってください。

# 2. 環境の複製

Windowsストアで入れたディストリビューションについて、複数使い分けられると便利（例えばWindowsストアで入手したばかりプラスαくらいの環境をexportしておけば、それをベースにして用途に応じた環境の使い分けが出来る）
のでやり方を確認しておく。

WindowsPowerShellからwslコマンドを使い、環境のexportとimportを行うことで環境が複製可能。
使うオプションは`wsl --help`を実行するかコマンドリファレンスの[Windows Subsystem for Linux を管理するための引数](https://docs.microsoft.com/ja-jp/windows/wsl/reference#arguments-for-managing-windows-subsystem-for-linux)などから確認出来る。
今回参照するのは以下の3つ：

- `--export`
- `--import`
- `--unregister`

## 2-1. 環境のexport

- `wsl --export <Distro> <FileName>`

で環境をtarファイルとしてexport出来る

例えば、以下のように環境`Ubuntu`が存在する場合：

```powershell
PS C:\Users\username> wsl -l -q
Ubuntu
```
以下のようにしてtarファイルにexport出来る：

```powershell
PS C:\Users\username> wsl --export Ubuntu .\WSL_IMAGES\BASE\ubuntu-20.04.tar
```

上の例では`<ユーザーのホームディレクトリ>\WSL_IMAGES\BASE`に事前に格納用のフォルダを作っていて、その中に`ubuntu-20.04.tar`の名前で保存している。（深い意味は無く、割と何でも良いと思われる）

ユーザーを作っただけのほぼまっさらなUbuntuの場合、上記のexportは10数秒~数10秒くらいで終わった。
tarのファイルサイズは1GB強といった感じ。

## 2-2. 環境のimport

- `wsl --import <Distro> <InstallLocation> <FileName>`

のようにしてtarファイルから環境を作成出来る。

このとき、作成した環境のイメージファイルをどこに置くのかも指定しないといけない。

例えば、

```powershell
PS C:\Users\username> wsl --import Ubuntu20.04-Base .\WSL_IMAGES\DISTRO\Ubuntu20.04-Base .\WSL_IMAGES\BASE\ubuntu-20.04.tar
```

のようにすると、`Ubuntu20.04-Base`という名前で先ほど作ったtarファイルをもとにした環境が作成出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/96ce688d-0f83-8956-8e94-43581c4a6cfa.png)


なお、上記のパス: `.\WSL_IMAGES\DISTRO\Ubuntu20.04-Base`について`DISTRO`にあたるところまでは事前にフォルダを作成する必要がある。
（ここのパスも深い意味は無く、自分で管理しやすいところに作れば良いと思われる）
ちなみに、ここで指定したパスには`ext4.vhdx`というハードディスクイメージのファイルが作成される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/f2a40189-1ca9-fe3d-00c1-f31f9eaf1a84.png)


ここから更に

```powershell
PS C:\Users\username> wsl --import Ubuntu20.04-Test .\WSL_IMAGES\DISTRO\Ubuntu20.04-Test .\WSL_IMAGES\BASE\ubuntu-20.04.tar
```

などとすることで、、同じtarファイルから異なる複数の環境を作成出来る。

### 注意：importで作った環境のログインユーザーについて

何故かデフォルトではrootでログインするようになってしまうのが難点。

- https://matsudamper.hatenablog.com/entry/2020/01/06/173939

などを参考にpowershellからレジストリを編集して変えることが出来るらしい。
（[後述](#4-1-1-ログイン設定の変更)のように、例えばWindows Terminalを使う場合なら起動オプションを編集することでも対処可能）

#### (追記)

[後述するwslconf](#5-1-wslconf)によっても対処出来る模様。

## 2-3. 環境の削除

- `wsl --unregister <Distro>`

とすることで不要な環境を削除出来る。

例えば、

```powershell
PS C:\Users\username> wsl --unregister Ubuntu20.04-Test
```

のようにして先ほど作った環境`Ubuntu20.04-Test`を削除出来る。

## (参考）

- https://zenn.dev/takajun/articles/50044292cf6060
- https://qiita.com/yamada6667/items/9e73193b0167cba2351d
- https://matsudamper.hatenablog.com/entry/2020/01/06/173939
- など

また、

- https://docs.microsoft.com/ja-jp/windows/wsl/use-custom-distro

によると、WSLから作ったtarファイル以外からでも環境を作成することが可能らしい。
（リンク先の例だとDockerで作ったCentOSコンテナのtarファイルを使うことで、WSL2にCentOSを入れている模様）

Windowsストアで入手出来ない、あるいは有料になってしまうディストリビューションも上記のようにして入れられる可能性がある。
（それこそDockerやその他仮想マシンなどで事足りるケースも多そうなので、そこまでしてWSL2で使いたいのかというところはあるが。。。）


# 3. clipboardの共有

可能ならWSL2のLinuxとホスト側のWindowsでclipboardを共有したいところ。
ターミナルから右クリックだったりCtrl + C/Vなどでなんとなくごまかせることもあるが、やはり機能としては弱くて不自由になる。
（個人的にはvimを使っているときにclipboard機能が使えないとかなり支障が出る）

X11を使うものと使わないものとで大きく2通りの対処方があるのでそれぞれまとめる。

## 3-1. VcXsrvを使ったclipboardの共有

※自分でやったのが半年以上前になるので詳しくは書いていない

Windowsで使えるフリーのX11サーバーソフトであるVcXsrvを使ってGUI機能をONにすることが1つ目の解となる。
WSL2を使う場合、WSL1のときよりも設定が数段面倒だったりするので注意。

（ちなみにWSLgが一般リリースされたら、ここの手順が無くなって非常に楽になるんじゃないかと期待している）
→ **(追記 2023-03-23)** 今ではWSLgがほとんどの環境で使えるため、わざわざサードパーティーのツールを入れるメリットは無いと思われる。WSLgは何もしなくてもデフォルトで有効なため、あとはaptなどのパッケージ管理ツールで[xclipやwl-clipboard](https://wiki.archlinux.jp/index.php/%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89)をインストールしてそれでおしまいだと思われる。

この方法は先行記事として

- [WSL2におけるVcXsrvの設定](https://qiita.com/ryoi084/items/0dff11134592d0bb895c)
- [開発環境構築（2020年版・WSL2+VcXsrv）](https://qiita.com/sus304/items/d3cfd91ab30b0e557997)
- [Windows Subsystem for Linux 2 (WSL2)でGUIプログラムを実行する](https://takake-blog.com/windows-subsystem-for-linux-2-wsl2gui/)

などがあり、この辺りを参考にして設定すれば良い。GitHubのissue: [Can't use X-Server in WSL2](https://github.com/microsoft/WSL/issues/4106)も参照のこと。

注意点として、WSL2を実行する仮想マシンとホストのWindowsをネットワークでつなぐ関係上、FireWallを開ける設定が必要になることが挙げられる（例えばパブリックでアクセスを許可する、などの必要）。WSL1よりも設定をゆるくしないと動かないので、状況次第では注意が必要かもしれない。

例えば以下：

- https://qiita.com/momomo_rimoto/items/51d533ae9529872696ce#%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%81%AE%E8%A8%AD%E5%AE%9A
- https://blog-jp.richardimaoka.net/20210411
- https://github.com/microsoft/WSL/issues/4139
- https://rin-ka.net/windows-x-server/#toc6
- https://www.aise.ics.saitama-u.ac.jp/~gotoh/HowToInstallUbuntu2004OnWSL2.html

などを参考に設定を行う。

上記X11周りの設定が出来ていれば、例えば`xclip`などを使ってLinux側のclipboardとWindows側のclipboardを接続・共有することが出来る。

## 3-2. win32yank

今回個人的に行ったケースだとclipboard共有だけできれば良くて（他のGUIソフトを使う訳じゃないので必ずしもX11は不要）、あとはあまりファイアーウォールの設定を変えたくない事情があったので代替策を検討した。

一番無難そうなのだとWindows側の`clip.exe`を呼び出すようにする方法があるらしい。

- https://kashewnuts.github.io/2020/06/11/wsl2.html#id3
- https://yanor.net/wiki/?UNIX/tmux/WSL%E3%81%A7Windows%E3%81%AE%E3%82%AF%E3%83%AA%E3%83%83%E3%83%97%E3%83%9C%E3%83%BC%E3%83%89%E3%81%AB%E3%82%B3%E3%83%94%E3%83%BC%E3%81%99%E3%82%8B
- https://blog.logicky.com/2021/01/11/203719?utm_source=feed
- https://blog.tmyt.jp/entry/2018/02/02/171311

が、

- https://mattn.kaoriya.net/software/wsl/20200530230631.htm

の「追記」などにあるように遅かったりするらしいのと、個人的にWSL2でWindowsの実行パスは引き継がないようにしたい（つまり普通には`clip.exe`を呼び出せない）ので、別の方法を検討した。

結果として、（あまり外部ツールは入れたくなかったが）[win32yank](https://github.com/equalsraf/win32yank)を入れる形で妥協することにした。

インストールはWSL2側で[リリースページ](https://github.com/equalsraf/win32yank/releases)から最新版（執筆時点で0.0.4）のx64あたりをダウンロードしてunzipし、`chmod +x`などで実行権限を付与してから環境変数`PATH`の通った場所に置く。


ここで、自分の場合はtmuxとNeoVimを使っているので

- [WSL2でvim/tmuxでクリップボード共有できるようにする](https://zenn.dev/u1tnk/articles/303ed2cd4fff6c)

を参考に設定を行った。すなわち、`.tmux.conf`に

```:.tmux.conf(追記分)
# vimのキーバインドを使う場合
bind-key -T copy-mode-vi y send-keys -X copy-pipe-and-cancel "win32yank.exe -i"
bind p run-shell 'win32yank.exe -o | xargs -0 -I{} tmux set-buffer -- {} && tmux paste-buffer'
```
を追記した。
なお、NeoVimを使う際は自分で"+"レジスタを指定してclipboardを使っているが、そのような使い方であれば特に`init.vim`などを変更する必要は無く、普通に動いた。
（NeoVimはClipboard toolとしてwin32yankを自動で認識するため。←`:checkhealth`などで確認出来る。Vim8.1などでは設定が必要と思われる。）

# 4. ターミナル環境の整備

デフォルトのコンソールは何かと使い勝手が良くないので、代替のツールを導入していく

## 4-1. [Windows Terminal](https://github.com/microsoft/terminal)

Windowsストアからインストールして使える。
なお、記事作成時のバージョンは`1.9.1942.0`である。（今後開発が進んでいくと設定がより便利になるかもしれない）

ここでは主に以下の設定を行う：

1. WSL2におけるログイン設定の変更
1. キーバインドの変更

### 4-1-1. ログイン設定の変更

Windows TerminalでWSLを開くと、デフォルトだとLinux側のホームディレクトリではなくWindows側のホームディレクトリで起動して鬱陶しいことが多い。
また、importして作ったユーザーだと設定を変えないとrootユーザーでログインするのもあまり気分が良くなかったりする。

この辺りはWindows Terminalで各環境（プロファイル）の設定を編集することで回避出来る。

まずはキーボードから`Ctrl + ,`を押すか、新しいタブを開くところのオプションから普通に「設定」を押して設定画面を新しいタブで開く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/cf40c83e-5b39-70c0-1791-09943acd1d76.png)

PowerShellやコマンドプロンプトなどと並び、作成済みの環境が左側の「プロファイル」に一覧として出ているので、適宜選択する。

起動の設定は「全般」から行うことができる。

ログインユーザーの設定は「コマンドライン」のコマンド編集により、
開始ディレクトリは「ディレクトリの開始」のパスを編集することで適宜変更出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/a1019702-d5f8-0332-c73e-a7a7755b8f87.png)**設定内容before**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/434ea3fc-17fb-843b-5bff-20cbe405bfff.png)**設定内容after**

コマンドラインのところは

```powershell
# before
wsl.exe -d <Distro>

# after
wsl.exe -d <Distro> -u <username>
```

のように変更する。（つまり、wslコマンドのオプションにユーザー指定を追加する）

「ディレクトリの開始」については、

```powershell
# before
%USERPROFILE% # ←Windowsでのホームディレクトリを表す環境変数

# after
\\wsl$\<Distro>\home\<username>
```

のように変更する。WSL2は`\\wsl$\`下にディスクがマウントされているので、そこの下にあるログインしたいユーザーのホームディレクトリのWindows上における絶対パスを指定している、といった感じ。

結果として、起動した直後の状態は以下のスクショのような感じで変化する：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/3ca2afb1-55c8-b2b1-1e04-839b1763fe4b.png)**起動後の状態before**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/8a22a8f7-1fbb-748b-98cc-fb721ce0a5e9.png)**起動後の状態after**
マシン名やユーザー名などを隠しているので分かりづらいが、とにかく起動直後に指定してユーザーでログインし、開始ディレクトリもそのユーザーのホームディレクトリ`~`になっている。

特に、importして作ったプロファイルのログインユーザーに関して、[先ほど書いたように](#注意importで作った環境のログインユーザーについて)基本的にはPowerShellからレジストリ操作をして変更を行う必要があったが、Windows Terminalでの使用に限れば不要な操作となる。

### 4-1-2. キーバインドの変更

個人的にはshell上からvimなどを呼び出して使うことが多いのだが、デフォルトだとWindows Terminalのキーバインドで`Ctrl + v`は「貼り付け」が当てられている。
すなわち、vimで矩形選択が出来ないなどといった状況になり、非常に困ったことになる。

キーバインド設定だが、設定画面の左から「操作」（2つあるが、キーボードっぽいアイコンの方）を開くと確認が出来る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/666e871c-b1e6-4b1d-5d5e-25d94b8f2ab1.png)
が、確認出来るだけでGUI上からの変更は執筆時点で未対応である。（将来的には出来るようになっているかもしれない）

現時点では上の方に説明が出ているように、JSONファイルを直接編集してキーバインドを変える必要がある。
今回は例として「貼り付け」に関して、`Ctrl + v`から`Ctrl + Shift + v`に変えることにする。

上のスクショの"JSONファイルを開く"をクリックすると設定のjsonが開く：

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/0634f8b8-57e1-1e06-9fbf-2efd5b5c2de9.png)

今回は`actions`の要素を編集する。
具体的には、`command`がpasteになっているものについて、`keys`を`ctrl+v`から`ctrl+shift+v`に変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/1b00b495-5feb-7592-6378-e58c357c2784.png)（編集後）

すると、めでたくキーバインドが以下のように変化する:


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/dd025592-efcd-481c-3944-0ccd2c684231.png)**before**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/ec987adb-3b87-3ef2-582a-91f8d5ea1a0a.png)**after**

これでめでたくvimで矩形選択を行う事ができる。
使用するツールなどによって他にも干渉するキーバインドがあるかもしれないが、大抵は上のようなやり方で適宜回避出来ると思う。

### 補足 fontの変更

shellのプロンプトやCUIベースのエディタをプラグインでリッチにしていたりすると特殊なフォントを入れたくなったりする。

こうした場合、Windows側で適当なフォントをインストールし、Windows Terminalの設定をいじることでフォントを入れられる。

日本語と様々な特殊記号をカバーしているフォントは例えば[Nerd fonts](https://github.com/ryanoasis/nerd-fonts)などが使える。

[リリースページ](https://github.com/ryanoasis/nerd-fonts/releases)から適当なものを選んでダウンロードして開き、その中からまた適当そうなものを選んで入れれば良い。（やたらたくさんあるが、全部を入れる必要は全く無い。zip内にあるファイルも最悪、例えば"Regular"とか書いてある普通っぽい1つを選ぶので問題無い）
zip内のotfファイルやttfファイルを開くと下のスクショのようになり、左上の「インストール」ボタンを押せば完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/4bbc5ae7-245c-35b6-f192-258bf25faa9f.png)

Windows Terminalにおけるフォント設定だが、
フォントは環境（プロファイル）毎に設定するので、変更したいプロファイルを設定画面の左から選択し、「外観」を選択することでフォントの設定画面を開ける。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/73efd4c6-1149-bb69-1196-74fc5b24f997.png)

「フォント フェイス」とあるところで使いたいフォントを選ぶことが出来る。
スクショではデフォルトの`Cascadia Mono`から`DejaVuSansMono Nerd Font Mono`に変えている。

余談だが、ここで選ぶフォントを`DroidSansMono Nerd Font Mono`にしたらtmuxの垂直pane分割時に縦線がうまく表示されない問題が起きた。
どのフォントでも正しく表示される保証は無いようなので、表示が崩れることがあればフォントを変えてみるとうまくいくかもしれない。

## 4-2. [wsltty](https://github.com/mintty/wsltty)

昔CygWinを使ってたり、[Git for Windows](https://gitforwindows.org/)のgit bashを使ったりしていた関係でminttyに馴染みがあり、今までデフォルトで使っていた。こちらも参考として紹介しておく。

[リリースページ](https://github.com/mintty/wsltty/releases)からインストーラーの`.exe`ファイルを落として普通にインストールする。
（scoopからもインストールできるが、自分はうまく動いたことが無い。。。）

実行するとおそらくwslのデフォルトになっているものを開くようになっている。

なお、インストーラーをダウンロード・実行するときにWindows Defenderやアンチウイルスソフトが悪意のあるソフトとして警告を出してくるのですごく気持ち悪いが、[このissue](https://github.com/mintty/wsltty/issues/252)などを見ると"I see no generic way to handle this problem."などとあるので結構どうしようも無いらしい？
気分は悪いが信用してインストールする。

- https://qazsedcftf.blogspot.com/2019/06/wsl-wsltty.html
- https://blog.cles.jp/item/10369


ちなみに複数環境を使い分けるには、スタートメニューに`<Distro> Terminal`のような感じで登録されるのでそれを選んで起動するようにする。（[参考](https://atmarkit.itmedia.co.jp/ait/articles/1812/13/news031.html)）
ちなみに%がつく方はWindowsのホームディレクトリで起動し、%がつかない方はLinux側のホームディレクトリで起動する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/9782c79e-5998-83b0-1e02-4e2948802063.png)


### 補足 fontの変更

フォントを入れる理由やWindows本体にフォントを追加する部分は[さっき](#補足-fontの変更-1)書いた通り。


フォントをインストールした後は、wslttyを起動してから左上にいる[Tuxくん](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%83%83%E3%82%AF%E3%82%B9)のアイコンをクリックし、Options...のTextを開くとFontの設定が出てくるので、Select...から使いたいものを選ぶ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680173/496e7cf9-9f55-41d4-4316-51384e5f16c0.png)

# 5. その他Tips(追記)

思いついたものを追記していく。

## 5-1. wsl.conf

`/etc/wsl.conf`を作成し、編集することでwsl周りの設定が出来る。
詳細はMicrosoftの公式ドキュメント「[wslconf を使用してディストリビューションごとの起動設定を構成する](https://docs.microsoft.com/ja-jp/windows/wsl/wsl-config#configure-per-distro-launch-settings-with-wslconf)」を参照すると良い。

個人的にはwsl側にWindowsの実行パスを混ぜたくないことが多かったりするので、

```:wsl.conf
[interop]
appendWindowsPath = false
```
などと書いていたりする。

また、先に`wsl --import`で作成した環境ではデフォルトのログインユーザーがrootになる旨を書いたが、
PowerShellから設定を変更したり、Windows Terminalを使う以外にも

```:wsl.conf
[user]
default = <username>
```
のようにして、`<username>`部分に作成したユーザーを書いておくことでも対処出来る。
（再起動すると反映される）

PowerShellでレジストリをいじるのは気が引ける場合や、Windows Terminalから以外にも呼び出すという人には 1つの選択肢になると思われる。

# 感想など

- Windows Terminal、以前はうまく設定できなくて使っていなかったが、うまく設定出来るとかなり便利だった。
  今後の進化に期待。
- クリップボード周り、大したことがしたい訳でも無いのに現状だと非常に手間がかかる印象。WSLgに期待。
- CPUやメモリを動的に割り当ててくれるWSL2は従来の仮想マシンなどと比べて一般的にかなり快適（改善の余地や色々と課題はあると思うが）。
   細かい設定などは割と面倒で疲れたが、それに十分見合うくらいにWSL2は便利だと再認識した。今後より使いやすくなっていくことに期待したい。