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


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 ルート・フォルダのパス

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

%LOCALAPPDATA%\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState

impsbl.hatenablog.jp

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

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

リセット いわゆる初期化
フル・パスの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"

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

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

wsl --unregister Ubuntu20210409

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

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

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