🐧

Linux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(8)- WSL

2024/03/17に公開

はじめに

これは、Linux 使いになりたい人向けに Intel N100 ミニ PC を使って開発環境を構築する方法を解説する記事の第8弾です。第1弾はLinux 使いになりたい人向けの Intel N100 ミニ PC で構築する開発環境(1) - 構築する開発環境について にあり、そこから第2弾へと続いています。そちらからご覧ください。

ここで使用する Intel N100 ミニ PC の仕様は次のものを前提とします。

項目 内容
OS Windows 11 Pro
CPU Intel N100
メモリ 16GB
ストレージ SSD 512 GB
画面出力端子 HDMI×2
WiFi 5G/2.4G
イーサネット RJ45×1
Bluetoot BT4.2
USB USB3.0×2/USB2.0×2

このマシンで最終的に Windows と Ubuntu Desktop が使えるように環境構築することを目指します。zenn.dev を購読している人のレベルを考えると、画面キャプチャはそれほど必要がないと考えているため少なめです。また、説明についても明示しないとわかりにくいと思われるものに絞っているので少なめです。

なお、実際に作業するときは、ネットワーク回線については数GBのデータをダウンロードしても問題ないものを使うようにしてください。作業の中には、数GBのデータをダウンロードするものも含まれてますので、テザリング環境では使用可能なパケットを使い切ってしまうこともあります。

今回は WSL について説明します。コマンド実行にあたっては Linux に慣れるということも考慮して、基本的に Git Bash を使うようにします。

WSL とは

Windows Subsystem for Linux (WSL) は、Windows OS の機能の一部で、Windows 上で Linux 環境を実行できる仕組みです。WSL を使うと、Windows コンピューター上で Linux ディストリビューションをインストールして実行できます。

WSL とディストリビューション

WSL は Windows OS のカーネル(kernel)の機能を使って Linux OS を動かせるようにした Windows のサブシステムなので、Hyper-V、VirtualBox といったハードウェアを仮想化するソフトウェアで用意する仮想マシン上にインストールした Linux OS と比較した場合、性能面、コンピューターリソース利用の効率面で有利です。Windows OS を動かしながら Linux OS を手軽に使えることから人気があります。

ここで、カーネルについて知らない人のために説明しておきます。コンピューターの基本ソフトウェアのことをオペレーティングシステム (Operating System、OS) といいます。ハードウェアとソフトウェアの間で仲介役となり、プログラムを実行するための基盤を提供するシステムです。コアの機能を提供するものをカーネル、ユーザーインタフェース機能を提供するものをシェルと言います。一般的な OS には、Windows、macOS、Linux、iOS、Android などがあります。

ところで、Linux ディストリビューションについて知らない人もいると思いますので、こちらも簡単に説明しておきます。Linux ディストリビューションとは、Linux OS のカーネルと、他のソフトウェアをパッケージングしてユーザーがインストールや利用できる状態にして提供しているものを指します。

有名な Linux ディストリビューションとしては、Debian 系の Debian、Ubuntu と、RedHat 系の Fedora、RedHatがあります。また、Slackware や Alpine といった軽量なディストリビューションなどもあります。WSL で利用可能なディストリビューションは Microsoft Store 経由で配布されています。

なお、WSL 用に自作のカスタムディストリビューションを使うこともできます。ただし、それを使うためには、システム設定の「開発者向け」の機能を有効にする必要があります。少しハードルが高いので、本記事では扱いません。

WSL の特徴

WSL は次に示す特徴を持っています。

  1. シームレスな統合: WSL は Windows OS と Linux OS の両方を同時に使いたい開発者向けに生産性の高い環境を提供するように設計されています。Windows デスクトップ上で Linux コマンドラインツールやアプリケーションが実行できます。

  2. Linux ディストリビューションのインストールと実行: WSL を使って、さまざまな Linux ディストリビューションをインストールして実行できます。Microsoft Store からインストールした Linux ディストリビューションは配信元が明確で安全性も高いと考えて良いです。

  3. コマンドラインツールとアプリケーションの実行: WSL を使って、Linux の便利なコマンドラインツールである gitgrepsedawk などを実行できます。また、Node.js、Python、Go、Java などのプログラミング言語用の開発環境もサポートしています。

  4. ファイルシステムの分離: Linux ディストリビューション用のファイルシステムは Windows OS のファイルシステムから分離された仮想ディスクに用意されるため、ファイルは Linux OS のファイルシステムで管理されます。

WSL のインストール

WSL のインストールにあたり、次のように winget コマンドで Canonical.Ubuntu.2204 をインストールしてある場合は、すでに WSL が使えるようになっていて、Ubuntu 22.04 の Ubuntu ディストリビューションがインストールされています。

winget install -e --id Canonical.Ubuntu.2204

ここでは、winget コマンドを使わずに WSL をインストールするときの手順について説明します。ここで説明する内容より、詳細を知りたい場合は、「WSL を使用して Windows に Linux をインストールする方法」をご覧ください。

WSL をインストールするには、管理者として実行するターミナルを使います。通常のターミナルで次のコマンドを実行すると、管理者として実行する Git Bash のターミナルが起動します。

PowerShell -Command "Start-Process 'C:\Program Files\Git\bin\bash.exe' -Verb RunAs"

PowerShell を使いたい場合は、次のコマンドを実行します。

PowerShell -Command "Start-Process 'C:\Program Files\PowerShell\7\pwsh.exe' -Verb RunAs"

管理者として実行するターミナルが開いたら、wsl コマンドへ --install オプションを指定して実行します。

wsl --install

これで、WSL がインストールされて、使えるようになります。また、同時に Ubuntu ディストリビューションがインストールされます。2024年3月16日時点では、Ubuntu ディストリビューションの中身の OS は Ubuntu のバージョン 22.04 でした。インストール時期によって、このバージョンは変わります。

なお、このとき、Ubuntu ディストリビューションが自動で起動します。もし自動で起動されない場合は、自分で起動して初期設定をしましょう。自動起動したときに必要な初期設定への対応については、後で説明します。ここでは、WSL のインストールについて説明を続けます。

ここで、--install オプションに WSL ディストリビューション名を指定すると、WSL ディストリビューションをインストールすることができます。有効な WSL ディストリビューション名の一覧を確認するには wsl --list --online コマンドを実行します。

wsl --list --online

2024年3月16日時点での有効な WSL ディストリビューション名の一覧は次のようになりました。

$ wsl --list --online
インストールできる有効なディストリビューションの一覧を次に示します。
'wsl.exe --install <Distro>' を使用してインストールします。

NAME                                   FRIENDLY NAME
Ubuntu                                 Ubuntu
Debian                                 Debian GNU/Linux
kali-linux                             Kali Linux Rolling
Ubuntu-18.04                           Ubuntu 18.04 LTS
Ubuntu-20.04                           Ubuntu 20.04 LTS
Ubuntu-22.04                           Ubuntu 22.04 LTS
OracleLinux_7_9                        Oracle Linux 7.9
OracleLinux_8_7                        Oracle Linux 8.7
OracleLinux_9_1                        Oracle Linux 9.1
openSUSE-Leap-15.5                     openSUSE Leap 15.5
SUSE-Linux-Enterprise-Server-15-SP4    SUSE Linux Enterprise Server 15 SP4
SUSE-Linux-Enterprise-15-SP5           SUSE Linux Enterprise 15 SP5
openSUSE-Tumbleweed                    openSUSE Tumbleweed

たとえば、この中から Ubuntu-22.04 ディストリビューションをインストールしたい場合は、次のようにします。

wsl --install Ubuntu-22.04

なお、インストールした WSL ディストリビューションを自動起動しないようにすることもできます。その場合は、wsl --install のオプションとして --no-launch を指定します。

たとえば、Ubuntu-22.04 ディストリビューションをインストールするときに、自動起動しないようにするコマンドは次のようになります。

wsl --instal Ubuntu-22.04 --no-launch

WSL の使い方

ここでは、WSL と、WSL ディストリビューションの使い方について説明します。

  • WSL ディストリビューションの起動
  • WSL ディストリビューションの停止
  • WSL ディストリビューションを使ったコマンド実行
  • WSL の更新

WSL ディストリビューションの起動

ディストリビューションを起動するには、--distribution オプション(-d オプション)を使い、起動するディストリビューション名を指定します。

wsl --distribution <ディストリビューション名>

短縮形は次のようになります。

wsl -d <ディストリビューション名>

たとえば、Ubuntu ディストリビューションを起動するコマンドは次のようになります。

wsl --distribution Ubuntu

次のように実行することもできます。

wsl -d Ubuntu

ここで、Ubuntu ディストリビューションを使う時には、初期設定としてユーザーの作成が必要です。そのため、自動で対話形式のユーザー作成のため処理が起動します。wsl --install コマンドを実行して自動で Ubuntu ディストリビューションがインストールされたときにも、この処理が自動で実行されます。

このときの対話形式でのやりとりについては、次のように必要な入力をして、ユーザーを作成します。

Please create a default UNIX user account. The username does not need to match your Windows username.
For more information visit: https://aka.ms/wslusers
Enter new UNIX username: user001  ← ユーザー名を入力
New password:  ← パスワードを入力。入力しても表示されない。
Retype new password:  ← パスワードと同じ文字列を入力。入力しても表示されない。
passwd: password updated successfully
Installation successful!

Ubuntu ディストリビューションを初めて起動したときには、ターミナルの画面に「Enter new UNIX username:」というプロンプトが表示されます。

ユーザー名は英字で開始する英数字文字列が使えます。自分が使いやすいものを指定してください。ここではユーザー名に user001 を指定して作成することにして、user001 を入力し、続けて Enter キーを入力します。

すると、「New password:」というプロンプトが表示されます。これは、Ubuntu を使う時のユーザー認証用のパスワードを指定するためのものです。ここの場合は、user001 ユーザーのパスワードを新規に指定するということになります。ここでは pass001 を指定するとします。

実際のパスワードについては、ランダムに選んだ3つの英単語を組み合わせ、一部を大文字とし、区切りに数字を使うといった工夫をして、推測されにくい複雑なものにしてください。なお、パスワードを入力しても表示されません。入力するパスワードをメモ帳などへ試しに入力してみてから、プロンプトへ入力するなどして、間違いがないようにしましょう。

パスワードを入力してから、続いて Enter キーを入力すると、「Retype new password:」という入力パスワード確認用のプロンプトが表示されます。パスワードで入力したものをもう一度入力します。こちらも入力した文字列は表示されません。続いて Enter キーを入力すると、指定したパスワードで認証できるユーザーが作成されます。

ユーザーが作成されると、そのユーザーでログインした状態でディストリビューションが起動します。ここでは Ubuntu ディストリビューションのプロンプトが表示されたら成功です。プロンプトについて、初期設定では、<ユーザー名>@<ホスト名>:/mnt/c/Users/User$ となります。

Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.133.1-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


This message is shown once a day. To disable it please create the
/home/user001/.hushlogin file.
user001@Win11Eval:/mnt/c/Users/User$

WSL ディストリビューションの停止

WSL ディストリビューションを停止するにあたり、インストールしているディストリビューション全部を停止する場合は、--shutdown オプション(-t)オプションを使います。

wsl --shutdown

特定の WSL ディストリビューションを停止するには、--terminate オプション(-t オプション)を使います。パラメーターにはディストリビューション名を指定します。

wsl --terminate <ディストリビューション名>

短縮形は次のようになります。

wsl -t <ディストリビューション名>

たとえば、Ubuntu ディストリビューションを停止するコマンドは次のようになります。

wsl --terminate Ubuntu

次のように実行することもできます。

wsl -t Ubuntu

これで Ubuntu ディストリビューションが停止します。

停止していることを確認するには wsl コマンドの --list オプション(-l オプション)へ --verbose オプション(-v オプション)を指定して実行します。次のように STATE が Stopped となっていれば停止しています。ここが Running となっている場合は起動中だということになります。

wsl --list --verbose

次のように実行することもできます。

wsl -l -v

起動するには -d オプションを使いました。Ubuntu ディストリビューションを起動して、exit でログアウトしてから、Ubuntu ディストリビューションの STATE を確認してみましょう。次のようになるはずです。

User@Win11Eval:~$ wsl -d Ubuntu
user001@Win11Eval:/mnt/c/Users/User$ exit
User@Win11Eval:~$ wsl --list --verbose
  NAME                   STATE           VERSION
* Ubuntu                 Running         2

WSL ディストリビューションのコマンド実行

WSL ディストリビューションのコマンドを実行するには、--distribution オプション(d オプション)で使用する WSL ディストリビューションを指定し、続いて実行するコマンドラインを指定します。このとき、コマンドラインは WSL ディストリビューションのユーザーのデフォルトのシェルを使って実行されます。

wsl -d <ディストリビューション名> <コマンドライン>

このようにすると、WSL の Ubuntu のプロンプトが表示されてからコマンドラインを実行するのではなく、Windows のターミナルからワンラインで Linux のコマンドを実行することができます。

似たようなもので、--exec オプション(-e オプション)というものがあります。こちらは、シェルを使わずに WSL ディストリビューションのコマンドを実行するときに使います。

wsl -d <ディストリビューション名> --exec <コマンドライン>

短縮形を使うと次のようになります。

wsl -d <ディストリビューション名> -e <コマンドライン>

たとえば、Ubuntu ディストリビューションで、/home/ のディレクトリーにあるファイルの一覧を表示するコマンドは、Linux では次のようになります。

ls /home/

これを、Windows のターミナルから実行するコマンドは、PowerShell だと次のようになり、出力結果は user001 となります。

wsl -d Ubuntu ls /home/

ただし、Git Bash を使うと次のようにエラーとなります。

$ wsl -d Ubuntu ls /home/
ls: cannot access 'C:/Program Files/Git/home/': No such file or directory

これは、Git Bash の場合は独自に Linux 環境と同じパス表現が使えるようになっているため、/home/user001 が自動で 'C:/Program Files/Git/home/user001/' に変換されてしまうからです。これを抑制するために、環境変数 MSYS2_ARG_CONV_EXCL が用意されています。この環境変数へ /home で始まるパラメーターについてパスの変換をしないように指定します。

MSYS2_ARG_CONV_EXCL='/home' wsl -d Ubuntu ls /home/

実際に、このコマンドを Git Bash で実行すると、次のように期待した通りの結果となります。

$ MSYS2_ARG_CONV_EXCL='/home' wsl -d Ubuntu ls /home/
user001

単純な Linux のコマンドは --distribution オプション(d オプション)で実行できますが、複雑なものは実行できません。例えば、/home/user001/hello.txt ファイルへ hello という文字列を保存するコマンドは、Linux では次のようになります。

echo hello > /home/user001/hello.txt

そのため、次のようにコマンドを実行すれば良さそうに見えますが、これだと期待する動作になります。

wsl -d Ubuntu echo hello > /home/user001/hello.txt

これを、Windows のターミナルの PowerShell で実行すると、次のようにエラーとなります。

OpenError: Could not find a part of the path 'C:\home\user001\hello.txt'.

Git Bash でも次のように実行するとエラーとなります。

$ MSYS2_ARG_CONV_EXCL='/home' wsl -d Ubuntu echo hello > /home/user001/hello.txt
bash: /home/user001/hello.txt: No such file or directory

これは、リダイレクトで使う記号 >wsl コマンドへ渡る前に Windows ターミナルで使われてしまうからです。

ここで、Linux では、コマンドを実行するための機能を提供するシェル(shell)というソフトウェアが用意されています。シェルには shbashzsh といったものがあり、Ubuntu ではデフォルトのシェルとして bash が使われるように設定されています。

シェルを使うと、指定した文字列をコマンドとして実行することができます。この機能を使うにあたり、どのシェルを使うと良いかというと sh になります。なぜかというと、多くの Linux ディストリビューションで sh コマンドはインストール直後から使えるようになっていて互換性が高いからです。Linux ディストリビューションによっては、bashzsh をインストールしないと、それらが使えないことがあります。

sh では -c オプションを使って、指定した文字列をコマンドを実行することができます。先程のコマンドを sh コマンドで実行する場合のコマンドは、次のようになります。

sh -c 'echo hello > /home/user001/hello.txt'

これを Ubuntu ディストリビューションで実行するコマンドは、次のようになります。

wsl -d Ubuntu sh -c 'echo hello > /home/user001/hello.txt'

さて、ここで、Ubuntu ディストリビューションでこのコマンドがどのように実行されるかについて考えてみます。--distribution オプションについて、「コマンドラインは WSL ディストリビューションのユーザーのデフォルトのシェルを使って実行されます。」と説明しました。

つまり、ユーザーのデフォルトのシェルが bash だった場合は、Ubuntu ディストリビューションで次のコマンドを実行しているのと同じだということになります。

bash -c "sh -c 'echo hello > /home/user001/hello.txt'"

これだとシェルの bashsh が無駄に使われることになります。ということで、このコマンドを実行するにあたっては、--exec オプションを使った方が良いということになります。--exec オプションであれば、余計なシェルを使わずに WSL ディストリビューションのコマンドを実行できます。

wsl -d Ubuntu --exec sh -c 'echo hello > /home/user001/hello.txt'

ちなみに、このように実行すれば、Git Bash と PowerShell の両方で同じコマンド表現となります。Git Bash を使うときは環境変数 MSYS2_ARG_CONV_EXCL の指定が必要な場合がありますが、--execsh -c を使うことで、この指定が不要となります。Git Bash を普段使うのであれば、このコマンド指定に慣れておいた方が良いでしょう。

なお、作成したファイルを確認するには次のように sh コマンドで cat /home/user001/hello.txt のコマンドを実行します。

wsl -d Ubuntu --exec sh -c 'cat /home/user001/hello.txt'

作成したファイルを削除するには次のように sh コマンドで rm /home/user001/hello.txt のコマンドを実行します。

wsl -d Ubuntu --exec sh -c 'rm /home/user001/hello.txt'

WSL の更新と設定

ここでは WSL の更新と設定について説明します。

  • WSL の更新
  • WSL 用ドライブの設定
  • デフォルトのディストリビューションの設定
  • WSL ディストリビューションの設定

WSL の更新

WSL をインストールした直後は、配布されたものが作成された時点の状態となっているので、ここで更新しておきましょう。WSL を更新するには --update オプションを使います。このコマンドは「管理者として実行する Windows ターミナル」から実行します。

wsl --update

このコマンドは、WSL を最新バージョンに更新するために使用します。このコマンドを実行すると、次の更新が行われます。

  • WSL 自体: WSL のコアコンポーネントとカーネルを最新バージョンへ更新
  • WSL の Linux ディストリビューション: インストールされている Linux ディストリビューションのパッケージリストを更新

実際に Git Bash でコマンドを実行した場合は、次のようになりました。2.1.5 はコマンドを実行するときの最新のバージョンになります。

$ wsl --update
更新プログラムを確認しています。
Linux 用 Windows サブシステムをバージョンに更新しています: 2.1.5。

WSL 用ドライブの設定

次に WSL 用ドライブの設定をしておきましょう。Windows OS と Linux OS のファイルシステムは別物なので、あまり Windows OS から Linux OS のファイルを操作することはしない方が良いのですが、ファイルの内容を編集したり、ファイルをコピーする程度なら問題なくできます。

Windows では WSL の Linux ディストリビューションのファイルは、次のような特別なパスで参照できるようになっています。

\\wsl$\<ディストリビューション名>

例えば、Ubuntu ディストリビューションの場合のファイルパスは次のようになり、これをエクスプローラーを使って開くことができ、クイックアクセスへ登録することもできます。

\\wsl$\Ubuntu

Windows から WSL の Linux ディストリビューションのファイルへアクセスしやすくするために、ドライブを設定しておきましょう。そのためには Windows ターミナルで net use コマンドを使います。パラメーターにドライブ名と Linux ディストリビューション用のファイルパスを指定します。

net use <ドライブ名>: \\wsl$\<ディストリビューション名>

ここでは U ドライブに Ubuntu ディストリビューションのファイルパスを設定することにしましょう。この場合のコマンドは、次のようになります。Git Bash と PowerShell の両方で実行できるようにするため、PoserShell -Command を使って実行するようにしています。

PowerShell -Command 'net use U: \\wsl$\ubuntu'

ちなみに、用意した U ドライブを切断するコマンドは、次のようになります。

PowerShell -Command 'net use U: /delete'

デフォルトのディストリビューションの設定

WSL のディストリビューションを指定しないで wsl コマンドを実行したときに使われるデフォルトのディストリビューションを指定するには --set-default オプション(-s オプション)を使います。

wsl --set-default <ディストリビューション名>

短縮形のオプションを使うときは次のようになります。

wsl -s <ディストリビューション名>

たとえば、Ubuntu ディストリビューションを削除してからインストールしなおすと、Docker Desktop 用のディストリビューションがデフォルトとなってしまって、wsl コマンドを実行するとエラーになるといったことが起きることがあります。そういったときに、デフォルトのディストリビューションを Ubuntu ディストリビューションへ再設定したりするときに使います。

その場合のコマンドは次のようになります。

wsl -s Ubuntu

WSL ディストリビューションの設定

WSL ディストリビューションごとの設定については、対象となるディストリビューションのファイルシステムにある /etc/wsl.conf ファイルで指定ができます。

なお、すべての WSL ディストリビューションに共通する設定をするためのファイルもあります。Git Bash だと ${HOME}/.wslconfig ファイル(PowerShell だと $env:UserProfile/.wslconfig)になります。これについては、本記事では扱いません。

たとえば、デフォルトのユーザーとして user001 を指定し、systemd を有効とし、ホスト名を Ubuntu-win11eval とする場合は、対象とする WSL ディストリビューションの /etc/wsl.conf ファイルの内容を次のようにします。

[user]
default=user001
[boot]
systemd=true
[network]
hostname=Ubuntu-win11eval

設定を変更したらディストリビューションを一度停止してから起動することで、設定が反映されます。

WSL ディストリビューションのエクスポートとインポート

ここでは、WSL ディストリビューションのエクスポートとインポートについて説明します。

  • WSL ディストリビューションのエクスポート
  • WSL ディストリビューションのインポート

WSL ディストリビューションのエクスポート

WSL ディストリビューションを本格的に使い始める前に、仮想ディスクのエクスポート方法を確認しておきましょう。エクスポートすることで、バックアップ相当のことができます。

WSL のディストリビューションの仮想ディスクをエクスポートするには --export オプションを使います。パラメーターにはディストリビューション名と保存するファイルのパスを指定します。続けてオプションを指定することもできます。

wsl --export <ディストリビューション名> <ファイルパス> [オプション]

ファイルは tar フォーマットのファイルとなるので、ファイルの拡張子は .tar とするのが良いでしょう。なお、ファイルパスに - を指定して標準出力(stdout)へ出力することもできます。また、オプションに --vhd を指定すると、仮想ディスクイメージのファイルとしてエクスポートすることができます。その場合は、ファイルの拡張子は .vhdx とするのが良いでしょう。

ところで、エクスポート対象となる WSL ディストリビューションが動作していると正しくエクスポートがとれません。エクスポートするときは、事前に WSL ディストリビューションを停止する必要が有ります。

Ubuntu ディストリビューションのエクスポート

それでは、Ubuntu ディストリビューションのエクスポートをしてみましょう。まず、Ubuntu ディストリビューションを停止します。

wsl -t Ubuntu

Ubuntu ディストリビューションのエクスポートを tar フォーマットのファイルの Ubuntu-20240101.tar へ保存するために、次のコマンドを実行します。-20240101 の部分はエクスポートした日付がわかるように、コマンドを実行するときの年月日などにしておくと良いので例としてつけてあります。

wsl --export Ubuntu Ubuntu-20240101.tar

また、仮想ディスクイメージでのエクスポートについては、Ubuntu-20240101.vhdx ファイルへ保存することにして、次のコマンドを実行します。

wsl --export Ubuntu Ubuntu-20240101.vhdx --vhd

仮想ディスクイメージファイルのパス

WSL ディストリビューションが使用している仮想ディスクのファイルパスを確認するには PowerSHell のコマンドが使えます。少し複雑なので説明は省略しますが、次のコマンドを実行することで確認ができます。

(Get-ChildItem `
  -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss `
| Where-Object { $_.GetValue("DistributionName") -eq '<ディストリビューション名>' } `
).GetValue("BasePath") + "\ext4.vhdx"

このコマンドのディストリビューション名を Ubuntu に置き換えた PowerShell スクリプトは次のようになります。これを check_vhdk.ps1 スクリプトファイルとして保存しておきます。

check_vhdk.ps1
(Get-ChildItem `
  -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss `
| Where-Object { $_.GetValue("DistributionName") -eq 'Ubuntu' } `
).GetValue("BasePath") + "\ext4.vhdx"

複雑なコマンドですが、スクリプトファイルにしておくと、Git Bash でも PowerShell でも次のように実行できます。

PowerShell -ExecutionPolicy Bypass -File "check_vhdk.ps1"

実際に実行すると、次のような結果となります。

$ PowerShell -ExecutionPolicy Bypass -File "check_vhdk.ps1"
C:\Users\User\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState\ext4.vhdx

実行結果から、C:\Users\User\(略)\LocalState\ にある ext4.vhdx ファイルがエクスポート対象の仮想ディスクファイルだということがわかります。システムクラッシュなどで wsl コマンドが使えないけどエクスポートをしたい場合には、こちらを直接コピーしてエクスポートすることができます。覚えておくと良いでしょう。

WSL ディストリビューションのインポート

エクスポートファイルから仮想マシンをインポートするには wsl コマンドの --import オプションを使います。パラメーターにはディストリビューション名、インストール先のパス、インポートで使うファイルのパスを順に指定します。続けてオプションを指定することもできます。

wsl --import <ディストリビューション名> <インストール先のフォルダのパス> <ファイルパス> [オプション]

オプションを指定しない場合は、指定されたファイルパスのファイルは tar フォーマットとして扱われて、インポートがされます。その結果、インストール先のフォルダに仮想ディスクイメージファイルが作成されます。なお、ファイルパスに - を指定して標準入力(stdin)からインポートすることもできます。

ここで、ファイルパスに .vhdx の拡張子の仮想ディスクイメージのファイルパス、オプションに --vhd を指定することもできます。この場合は、指定されたインストール先のフォルダに仮想ディスクイメージのファイルのコピーが作成されます。

Ubuntu の tar ファイルのインポート

先程エクスポートした Ubuntu-20240101.tar を使って Ubuntu をインポートします。まず、Git Bash で mkdir コマンドでインポート先のフォルダを用意します。

mkdir /c/Users/User/wsl-import

それから、Git Bash でディストリビューション名に Ubuntu-20240101、インポート先に /c/Users/User/wsl-import、ファイルパスに Ubuntu-20240101.tar を指定してインポートします。

ここでは Ubuntu-20240101.tar ファイルがあるディレクトリーをカレントディレクトリーとして、次のコマンドを実行します。

wsl --import Ubuntu-20240101 \
  /c/Users/User/wsl-import \
  Ubuntu-20240101.tar

インポート後に、wsl -d Ubuntu-20240101 コマンドを実行して Ubuntu-20240101 ディストリビューションを起動すると、初期起動時に必要だったユーザーの追加は必要なく、user001 が登録された状態で Ubuntu-20240101 ディストリビューションで Linux コマンドが実行できるようになります。

ただし、Ubuntu ディストリビューションとは違って、デフォルトで root ユーザーで Linux のコマンドが実行される設定になっています。後に説明する /etc/wsl.conf ファイルを用意することで、user001 ユーザーで Linux のコマンドが実行されるように設定できます。

それでは、実際に Ubuntu-20240101 ディストリビューションを起動して、/home/user001 が存在することを ls コマンドで確認して、user001 が登録されていることを確認してみましょう。

$ wsl -d Ubuntu-20240101
Welcome to Ubuntu 22.04.3 LTS (GNU/Linux 5.15.146.1-microsoft-standard-WSL2 x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage


This message is shown once a day. To disable it please create the
/root/.hushlogin file.
root@Win11Eval:/mnt/c/Users/User# ls /home/
user001
root@Win11Eval:/mnt/c/Users/User# exit
logout

実際に使ってみると、ホスト名も Ubuntu となっていて、Ubuntu ディストリビューションと区別がつきにくいことに気がつきます。これについても、後で説明する /etc/wsl.conf で変更することができます。

Ubuntu の仮想ディスクイメージのインポート

次に Ubuntu の仮想ディスクイメージをインポートしてみます。なお、この方法だと新しい vhdx ファイルがインポート先のフォルダに作成されるので、ディスク容量に余裕がないとインポートができません。ディスク容量に余裕がないときは、後で説明する --import-in-place オプションを使う方が良いでしょう。

ここでは、新しいディストリビューションとしてインポートするのではなく、Ubuntu-20240101 ディストリビューションとしてインポートしてみることにします。なお、すでにインストール済みのディストリビューションへインポートすることはできないので、先にディストリビューションの登録を解除する必要があります。

ディストリビューションの登録を解除するには、wsl コマンドの --unregister オプションを使います。パラメーターにはディストリビューション名を指定します。

wsl --unregister <ディストリビューション名>

それでは Ubuntu-20240101 ディストリビューションの登録を解除しましょう。

wsl --unregister Ubuntu-20240101

次に、Git Bash で Ubuntu-20240101.vhdx ファイルがあるディレクトリーをカレントディレクトリーとしてインポートのコマンドを実行します。ここでは、tar フォーマットのファイルを使ったときと違って、--vhd オプションを指定することで仮想ディスクイメージのファイルからインポートします。

wsl --import Ubuntu-20240101 \
  /c/Users/User/wsl-import \
  Ubuntu-20240101.vhdx --vhd

インポート後に、wsl -d Ubuntu-20240101 コマンドを実行して Ubuntu-20240101 ディストリビューションを起動して、tar フォーマットのファイルからインポートしたときと同様に動作確認します。

Ubuntu 公式サイトのアーカイブをインポート

Ubuntu については、公式サイトで WSL 用のアーカイブファイルが公開されています。コマンドを使ってインポートする場合は、Microsoft Store 経由で Ubuntu ディストリビューションをインストールするのではなく、こちらをダウンロードして使うようにした方が手軽に感じるかもしれません。

ここでは Git Bash で Ubuntu 22.04 のアーカイブをダウンロードしてインポートしてみましょう。Git Bush では curl コマンドというコマンドを使うことで Web サイトからファイルをダウンロードすることができます。

Git Bash では、次のスクリプトを用意して実行することで、Ubuntu22 ディストリビューションとして Ubuntu の公式サイトで公開されている WSL 用のアーカイブファイルをインポートすることができます。

install_ubuntu22.sh
DISTRO_NAME=Ubuntu22
IMPORT_PATH=${HOME}/${DISTRO_NAME}-import
DL_URL=https://cloud-images.ubuntu.com/wsl/jammy/current
FILE_NAME=ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz

if [ ! -e ${IMPORT_PATH} ]; then mkdir ${IMPORT_PATH}; fi
if [ ! -e ${FILE_NAME} ]; then
  curl -LO "${DL_URL}/${FILE_NAME}"
fi
wsl --import ${DISTRO_NAME} ${IMPORT_PATH} ${FILE_NAME}

これを実行します。

sh ./install_ubuntu22.sh

インポートした Ubuntu22 のディストリビューションを起動すると root で Linux コマンドの実行ができるようになります。

このようにインポートした WSL ディストリビューションは普段使用する WSL ディストリビューションとは違って、登録解除が手軽にできるような状態にしておいて、試用で使うことができます。

初期にインストールするパッケージがある場合は、次のような init.sh スクリプトを用意しておいて、これを実行すると良いでしょう。

init.sh
#!/bin/sh
apt-get update && apt-get upgrade -y
apt-get install -y build-essential

また、試用で使う環境の構築にあたっては、ユーザー登録などをするスクリプトを用意しておくと便利です。たとえば、次のような add-user.sh スクリプトを用意しておくと良いでしょう。

add-user.sh
#!/bin/sh
if [ "x${USER_NAME}" = "x" ]; then
  USER_NAME=user001;
fi
groupadd -g 1000 ${USER_NAME}
useradd -u 1000 -g 1000 -G sudo -s /bin/bash -m ${USER_NAME}
passwd -d ${USER_NAME}
cat << EOS > /etc/wsl.conf
[user]
default=${USER_NAME}
[boot]
systemd=true
EOS

ここでは Git Bash で init.shadd-user.sh/c/Users/User ディレクトリーに用意したとして、次のコマンドを実行して初期化します。

PowerShell -Command 'wsl -d Ubuntu22 /mnt/c/Users/User/init.sh'
PowerShell -Command 'wsl -d Ubuntu22 /mnt/c/Users/User/add-user.sh'

なお、ユーザーを user001 以外、たとえば user002 にしたい場合は、add-user.sh を実行するコマンドを次のようにします。

PowerShell -Command 'wsl -d Ubuntu22 sh -c "USER_NAME=user002 /mnt/c/Users/User/add-user.sh"'

ちなみに、Git Bash で実行する前提なら、次の ${HOME}/install_ubuntu22_all.sh を用意すれば、install_ubuntu22.shinit.shadd-user.sh を全部一度に実行することができるようになります。

install_ubuntu22_all.sh
export MSYS2_ARG_CONV_EXCL='/mnt'
sh ${HOME}/install_ubuntu22.sh
wsl -d Ubuntu22 /mnt/c/Users/User/init.sh
wsl -d Ubuntu22 /mnt/c/Users/User/add-user.sh

これを使うには Git Bash で install_ubuntu22_all.sh ファイルがあるディレクトリーで次のコマンドを実行します。

sh ${HOME}/install_ubuntu22_all.sh

このようにして Ubuntu22 ディストリビューションを用意したら、追加した設定を有効化するために、一度停止してから起動します。

wsl -t Ubuntu22
wsl -d Ubuntu22

Ubuntu22 のシェルが起動したら、登録したユーザーのパスワードを passwd コマンドを使って新規登録します。ユーザー作成時にパスワードの有効期限が切れた状態としてあるので、これを設定しない場合は、ユーザーのパスワードが無効のままとなります。実際にパスワード登録するときの画面は次のようになります。

user001@Win11Eval:/mnt/c/Users/User$ passwd
New password:
Retype new password:
passwd: password updated successfully

これで Ubuntu22 ディストリビューションを使えるようになります。作業が終わったら、exit コマンドを使ってログアウトしておきます。

user001@Win11Eval:/mnt/c/Users/User$ exit
logout

仮想ディスクをそのまま使用するインポート

既存の仮想ディスクイメージファイルを使用して、WSL ディストリビューションをインストールするには、--import-in-place オプションを使います。このオプションを使うと、仮想ディスクイメージファイルのコピーをしません。このオプションを使ってみましょう。

まず、Ubuntu22 ディストリビューションについて、初期設定が済んだ仮想ディスクイメージをバックアップします。

Git Bash で Ubuntu22 ディストリビューションを停止してから、仮想ディスクイメージファイルをコピーして Ubuntu22.vhdx へバックアップをとっておきます。それから Ubuntu22 ディストリビューションを削除します。

これらの作業をするためのコマンドは次のようになります。

wsl -t Ubuntu22
cp ${HOME}/Ubuntu22-import/ext4.vhdx Ubuntu22.vhdx
wsl --unregister Ubuntu22

最後に実行した wsl --unregister Ubuntu22 のコマンドにより、${HOME}/Ubuntu22-import/ext4.vhdx は削除されます。バックアップしてあった Ubuntu22.vhdx${HOME}/Ubuntu22-import/Ubuntu22.vhdx へ移動して、そのまま使うように --import-in-place オプションでインポートしてみましょう。

これらの作業をするためのコマンドは次のようになります。

mv Ubuntu22.vhdx ${HOME}/Ubuntu22-import/
wsl --import-in-place Ubuntu22 ${HOME}/Ubuntu22-import/Ubuntu22.vhdx

それから Ubuntu22 のディストリビューションを起動すると、Ubuntu22 起動時に登録したユーザーが存在した状態となっていることが確認できます。

wsl -d Ubuntu22

Discussion