Technically Impossible

Lets look at the weak link in your statement. Anything "Technically Impossible" basically means we haven't figured out how yet.

WSL環境を作って壊す、覚書、2021年版 サービス操作からディストリビューション操作の基礎

Windows上でLinuxを稼働させる際、WindowsLinuxの中継レイヤーとして機能するのがWSL (Windows Subsystem for Linux)だ。Hyper-Vなどの仮想環境に比べて、WSL上で稼働するLinuxは起動が早く、消費リソースも少ない。特にノートPCのように何かとリソースが制限されている環境で動作させるのに都合が良い。
開発環境やサーバー用途としてデスクトップ上で常用するのも良いが、簡単に環境を構築でき、素早く起動し、削除してもWindows環境を汚さない特性は、繰り返し使い捨てる環境の構築には絶好の機能だ。

WSL関連の投稿を繰り返していると、WSLそのものについて一度整理しよう、という気になった。WSLの動作には、次の3要素が関係している。

  1. ホストとなるWindowsのこと
  2. WSLそのもの(以降、WSLとはWSL2を指すこととする)
  3. WSL上で動作するLinux(以降、ディストリビューションと呼ぶ)

多用するのは2、3だが、メタ的に3に関わる操作を、2から行うこともある。典型的なのがディストリビューションのバックアップだ。
それぞれの項目ごとに、典型的な操作、必要となるだろう知識をまとめたのが、今回の投稿だ。

公式情報

まずは公式情報を確認したい。リファレンス、引用元として、次のサイトを参照している。
docs.microsoft.com

WSL

WSL1、WSL2の違い

基本的にWSL2の方が優れており、WSLと言えばWSL2を選択することで問題はない。
しかしWindowsディストリビューション間でのファイル処理を伴い、その頻度や依存が大きな場合には、WSL1の利用が推奨されている。それは次の理由による。

  1. Windowsディストリビューション間のファイル処理パフォーマンスは、WSL1の方が良い。
  2. ディストリビューション稼働で蓄積されたキャッシュは、WSL終了まで解放されない。

前者は簡単に解決できる。マウントしている、あるいは参照しているドライブやフォルダ、ファイルなどをディストリビューション内に格納してしまうことだ。WSL内でファイル操作を完結できれば、WSL2の方がパフォーマンスに勝れる。

後者の解決は難しい。ディストリビューションの動作中に蓄積されるメモリ・キャッシュは、Windowsへ返還される。WSL2の場合、そのタイミングはWSLの終了時だ。つまり、次の特性のある用途では、ディストリビューションを長時間、連続稼働させるほど、Windows上のRAMを消費し続けることになる。

このような用途では、WSL1を使うことが推奨されている。

WSL 2's memory usage grows and shrinks as you use it. When a process frees memory this is automatically returned to Windows. However, as of right now WSL 2 does not yet release cached pages in memory back to Windows until the WSL instance is shut down. If you have long running WSL sessions, or access a very large amount of files, this cache can take up memory on Windows. We are tracking the work to improve this experience on the WSL Github repository issue 4166.

サービスとしてのWSL

f:id:espio999:20210409205221p:plain
WSLはWindows上で動作する、LxssManagerという名称のサービスだ。WSLのサービスを意図的に停止、再起動などさせる場合には、GUIであればタスクマネージャーやサービスから操作すればよいし、PowerShellによるコマンド操作であれば、次のコマンドのうち、必要なものを実行すればよい。

Start-Service -Name LxxManager
Suspend-Service -Name LxssManager
Restart-Service -Name LxssManager
Stop-Service -Name LxssManager

WSL仮想サーバーへのリソース割り当て

WSLが利用する仮想サーバーに割り当てるCPU、RAM、スワップ・サイズ等々を設定することができる。設定は”.wslconfig”に記述する。そのファイルは、次にパスに格納する。

%HOMEPATH%\.wslconfig

CPU、RAMのデフォルト割当は次のようになっている。

CPU ホスト搭載量と同数
RAM 次のいずれか、少ない方
・8GB
・搭載量の50%

ファイルの記述については、次のページの「WSL 2 Setting」を記述を参照すると良い。
docs.microsoft.com

WSLの仮想ディスク

WSLの仮想マシンは、ディストリビューションごとに仮想ディスク(VHDファイル)をマウントしている。そのサイズは最大256GBの範囲で、自動的に拡張される。

必要な場合、次のサイトの「Expanding the size of your WSL 2 Virtual Hard Disk」に記載されている手順で、256GB超に拡張することができる。
仮想ディスクの拡張には、ホスト、ディストリビューション双方からの操作が要求されることに注意すること。

ホスト側 コマンドdiskpartによるサイズ拡張
ディストリビューション コマンドresize2fsによるサイズ拡張

docs.microsoft.com

ディストリビューション

ルート・フォルダ

WSL上で稼働するディストリビューションのファイル・システムは、Windowsファイル・システム上に包含されている。

そのファイル・システムへの最も簡単なアクセス方法は、Windowsから「\\wsl$」を参照することだ。Windowsから見たとき、各ディストリビューションのパスは次のようになる。

ルート
\
\\wsl$\ディストリビューション名\
ホーム
~
\\wsl$\ディストリビューション名\home\ユーザー名\

そして、レジストリを参照することで、導入したディストリビューションのルート・フォルダが、Windows上のどこに位置しているのかを確認することができる。導入したディストリビューションは、個別のGUIDとして定義されている。

コンピューター\HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss
DistributionName 対応するディストリビューション
BasePath ルート・フォルダのパス

f:id:espio999:20190130225851p:plain

画像はUbuntuのものだ。基本的にユーザー・フォルダのAppData配下に格納される。フル・パスは次のようになる。AppDataがどのようなフォルダなのかは、次のエントリを参照してほしい。

%LOCALAPPDATA%\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState

impsbl.hatenablog.jp

初期化、アンインストール

ディストリビューションへの操作は、「アプリの機能」からできることと、wslコマンドを通じてできることに分かれている。「アプリの機能」から実行できるのは、ディストリビューションの初期化、アンインストールだ。
f:id:espio999:20190130225930p:plain
f:id:espio999:20190130225953p:plain

リセット いわゆる初期化
フル・パスのLocalState配下のフォルダが削除される。
具体的にはフォルダrootfsとtemp。
Ubuntuを再実行すると、両フォルダが新規作成される。
アンインストール ディストリビューションのアンインストール
Ubuntuの場合、フル・パスのCanonical...が削除される。

一方、コマンドには”unregister”というオプションが用意されている。これは上記「アンインストール」に該当する。特にMicrosoft Store以外から導入したディストリビューションへの操作において、有効に機能する。具体例を後述する。

インポート、エクスポート、あるいはバックアップ、リストア

WSLは、開発環境のように作っては壊す、繰り返し使い捨てる環境の構築に絶好の機能だが、いつも一から作り直すのは手間なときもある。ある程度「作られた」環境を使い捨てしたい時もあるはずだ。
そのようなときディストリビューションをバックアップ、リストアできれば良いと思う。そして、その機能はimport、exportオプションとして実装されている。
加えて、これらのオプションを活用することで、同一のディストリビューションを複数登録し、目的に応じて使い分けすることもできる。さらには、Microsoft Storeでは提供されていないディストリビューションを取り込むための応用にも活用できる。この方法については後述の「Dockerコンテナからのインポート」で取り上げている。

exportオプションでは、指定されたディストリビューションがtarファイルとして出力される。例えばディストリビューションUbuntuを適当なファイルへ出力するとしよう。
コマンドはこのようになる。ファイル・パスが引用記号で囲まれているのは、半角スペースが含まれているからだ。

wsl --export Ubuntu "D:\user temp\20210409\blog\exported-ubuntu.tar"

importオプションを用いて、このファイルを指定されたフォルダへ、指定されたディストリビューションとして、取り込む。ここで注意したいのは、次の2点だ。

  • ディストリビューションは原則としてCドライブ中に格納することになっている。
    • Cドライブ以外にもimportできるのだが、動作は保証されない。

The Windows Subsystem for Linux only runs on your system drive (usually this is your C: drive). Make sure that distributions are stored on your system drive:

導入先となるフォルダを作成して、インポート・オプション付きのwslコマンドを実行する。ディストリビューション名と、フォルダ名を一致させる必要もない。

ディストリビューション Ubuntu20210409
インストール先 $env:LOCALAPPDATA/WSL_import/TEST20210409
つまり
C:\Users\[user name]\AppData\Local\WSL_import\TEST20210409
mkdir $env:LOCALAPPDATA/WSL_import/TEST20210409
wsl --import Ubuntu20210409 $env:LOCALAPPDATA/WSL_import/TEST20210409 "D:\user temp\20210409\blog\exported-ubuntu.tar"

f:id:espio999:20210409210011p:plain

WSLは追加されたディストリビューションを認識し、rootでも既存ユーザー(Ubuntuには、あらかじめwsluserというユーザーが登録されていた)でもログインできることが分かる。

しかしインポートしたディストリビューションは、手動でアンインストールしなければならない。先に紹介したunregisterオプションは、この時に利用する。

wsl --unregister Ubuntu20210409

コマンド実行後、インストール・フォルダ配下の一切が削除される。
f:id:espio999:20210409205942p:plain

Dockerコンテナからのインポート

Dockerコンテナからexportしたtarファイルを、WSLへimportすることができる。この方法を活用すると、Microsoft Storeでは提供されていないディストリビューションも、WSL上で動作させることができる。
impsbl.hatenablog.jp