前回は、wsl.exeコマンドを使ったバックアップとリストアを解説した。今回は、Linuxコマンドを使ったリストアと、Win32コマンド(PowerShell)を使ったWSLディストリビューションの登録方法を解説する。検証には、Microsoftストア版WSL Ver.1.2.2.0を利用した。

一部のファイルのみリストア

場合によっては、バックアップから、特定のファイルのみを取り出したい場合がある。このような場合には、 バックアップをtar形式で行ない、Linux側でtarコマンドを使って一部を取り出す。

wsl.exeの“--export”では、Windows 11に搭載されているtarコマンド(tar.exe)が使われるが、これはBSD系Unixで主に使われているbsdtarであり、Linuxで広く使われているGNU tarとはオプションなどに若干の違いがある。ここでは、WSLのLinuxから使うことを想定してGNU tarを解説する。なお、ここで解説した範囲では、GNU tarとbsdtarのオプション指定は同じである。

Windows 11に搭載されたbsdtarは、GNU tarとは異なるアトリビュートをtarファイル内に保存し、その場合、

tar: Ignoring unknown extended header keyword 'LIBARCHIVE.xattr.security.capability'

tar: 未知の拡張ヘッダキーワード 'LIBARCHIVE.xattr.security.capability' を無視

というエラーメッセージが表示されることがある。シングルクオート内は異なる文字列になることもある。これは、bsdtarが出力したtarファイル中のキーワードをGNU tarが無視したという警告であるため、そのまま実行しても問題ない。

tarコマンドは多数のオプションがあり、さらに古くからのコマンドであるため、初期Unixで使われていたオプション文字(ハイフン)を使わないオプション指定も可能など複雑なオプション体系をもつ。ここでは、できるだけ、GNUのロングオプション形式を使った方法を解説する。(表01)は、tarコマンドの主な処理指定オプション、(表02)は、併用するオプションを示す。基本的にtarコマンドは、処理を指定するオプションとその動作を指定するオプションの大きく2つのオプションがある。

■表01

■表02

まずは、tarファイルに含まれているファイルの一覧からだ。それには、

tar␣--list␣[<オプション>]␣--file␣<tarファイルパス>␣<リスト出力するパス>

とする。取り出したいファイルのパスは、tarファイル内でのパス指定を行なう。なお、ファイルのサイズやパーミッションなど詳細な情報を得たい場合には、“ --verbose”オプションを付ける。

tarファイルは、通常、ルートディレクトリを含まない相対パスでファイルやディレクトリをアーカイブしてある。<リスト出力するパス>は、tarファイル内で指定されているパスを指定し、先頭部分が一致するファイル、ディレクトリが表示される。

たとえば、カレントディレクトリにある「file.tar」から、「./home」に格納されているファイル一覧を表示させるには、

tar --list --verbose --file ./file.tar ./home

とする(写真01)。

写真01: tarコマンドで--listオプションにより、アーカイブ中の“./home”ディレクトリ以下を表示させたところ。出力末尾に警告表示があるが、bsdtarとGNU tarの違いで無視してかまわない

実際にファイルを取り出す場合には、tarコマンドを実行したときのカレントディレクトリが起点になることに注意が必要だ。WSLディストリビューションでは、前記のようにユーザーのホームディレクトリは、tarファイル内では“./home”以下にある。もし、tarコマンドを“/temp”で実行し、ユーザーのホームディレクトリを取り出せば“/temp/home”以下に書き込まれる。

tarコマンドを使いバックアップファイルから特定のファイルを取り出すには、以下の書式を使う。注意するのは、tarでは、ファイルだけでなく、ファイルのパーミッションや所有者、最終変更日時などのメタ情報もリストアされるという点である。

tar␣--extract␣--file␣<tarファイルパス>␣<出力するパス>...

ユーザーshiodaのホームディレクトリにある「/home/shio/shiodafile」と、「/etc/passwd」を取り出すには、

tar --extract --verbose --file ./file.tar ./home/shio/shiodafile ./etc/passwd

とする(写真02)。2つのファイルの出力先は、カレントディレクトリが起点となる。カレントディレクトリが/tmpならば、/tmp/home/shio/shiodafileと/tmp/etc/passwdになる。

写真02: Linux側で/tmpディレクトリでアーカイブから2つのファイルを取り出したところ。相対パスで出力されるため、2つのファイルは、カレントディレクトリ以下にサブディレクトリが作られて配置される

Win32側の機能を利用する

WSLディストリビューションに関する操作は、Win32側からも行なうことができる。WSLディストリビューションは、レジストリに登録されている。レジストリキー自体は、Microsoftのドキュメントにも記載されているが、レジストリエントリに関しては公開されておらず、各エントリの説明などは筆者が調べたものであることをご理解いただきたい。今後のバージョンアップなどで変更される可能性もある。レジストリを変更する場合には、あくまでもご自身のリスクで行なっていただきたい。

WSLディストリビューションが登録されているのは、

HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Lxss

である。ここにGUIDを使ったサブキーがあり、これがWSLディストリビューションの登録情報になる。

各サブキーには、(表03)のような値がある。これらを表示させるには、レジストリエディタを使うか、PowerShell(Windows PowerShellも可)から以下のコマンドを使う。

■表03

Get-ChildItem HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Get-ItemProperty

サブキーのGUIDは、UUIDのVer.4が使われており、乱数で生成されるものだ。このGUIDで作られたサブキーに前掲の表の値を書き込むことで、ディストリビューションが登録できる。

GUIDキーに登録されるデータのうち、「DefaultUid」、「Version」に関しては、あとからwsl.exeを使って変更が可能で、ディストリビューションのローカルファイルシステムにvhdxファイルを使うならば「Version」は2になる。「Flags」と「State」は、筆者が調べた範囲では、すべて同一の値が使われていた。「PackageFamilyName」は設定しなくても動作するようだ。ここから考えると、登録時にユーザーが指定する必要があるものは、「DistributionName」と「BasePath」であり、後者は、vhdxファイルのパスを指定する。「VhdFileName」は、vhdxファイルのファイル名がext4.vhdx以外の場合に指定する必要があるが、そうでない場合には指定は不要である。

注意するのは、「DistributionName」は、wsl.exeコマンドで、ディストリビューションを指定するものであるため、他の登録内容とは衝突しないものを選ばなければならない点である。

また、WSLディストリビューションの登録を解除するには、HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxssキー以下のGUIDエントリを削除する。これは、wsl.exeの“--unregister”オプションと同等である。ただし、どちらの場合も、Microsoftストアからインストールしたディストリビューションは、登録は解除されてもパッケージとしては残ることに注意されたい。

手動でディストリビューションを登録する

ここでは、PowerShellから、レジストリを操作して、WSLにディストリビューションを登録する方法を解説する。これはMicrosoftストア版WSLバージョン1.2.2.0で行なった。

WSL2ディストリビューションは、レジストリに登録されていて、新規追加などは、レジストリ追加で行なうことが可能だ。レジストリエディタを使って手動で行なうことも不可能ではないが、ここでは、PowerShell(Ver.7.3)を使って、コマンドラインで行なう方法を解説する。なお、前提として、wsl.exeのエクスポートなどで作成したvhdxファイルを適当なディレクトリ(C:\Temp\wsltest)に配置し、ファイル名をext4.vhdxに変更してある。

手順としては、GUIDを生成して、レジストリキーを作り、レジストリエントリ(名前、種類、データ)を設定する。設定するのは(表03)とおなじもの。GUIDの生成は、インターネットサイトを利用してもいいし、Visual StudioやWindows SDKに付属のuuidgen.exeもある。しかし、PowerShellを使えば、簡単に生成が行える。以下、PowerShellを使って、レジストリ設定を行なう手順を示す。

GUID(Ver.4)は、New-Guidコマンドで生成できる。Ver.4は、乱数を使って生成するもので、実行するたびに異なるGUIDが出力される。ここでは、レジストリキーとして繰り返し使うので、変数($p)にレジストリキーとして格納しておく(写真03#%REG%#)。

$p="HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss\{$(New-Guid)}"

写真03: PowerShellからディストリビューションの登録を行なったところ。対象仮想ハードディスクファイルは、ext4.vhdxになっているため、ファイル名の指定は行なっていない。先頭で実行したwsl.exe -l -vの出力にはなかった“TestWSL”の名前でディストリビューションが登録され、起動も行える。なお、画面写真撮影の都合からNew-ItemPropertyコマンドの出力は、Out-Nullコマンドにリダイレクトして抑制している

確認は、“$p”を入力してエンターキーを押せばよい。

次にこれを使ってレジストリキーを作成する。

New-Item -Path $p

キーができたので、レジストリエントリ6個を登録する(リスト01)。追加には、New-ItemPropertyコマンドを使い、パスを登録した変数$pを“-Path”オプションの引数として指定する。

(■リスト01)

New-ItemProperty -Path $p -Name DistributionName -PropertyType String -Value <追加するディストリビューションの名前>

New-ItemProperty -Path $p -Name BasePath -PropertyType String -Value <追加するvhdxファイルのあるフォルダパス>

New-ItemProperty -Path $p -Name DefaultUid -PropertyType DWord -Value 1000

New-ItemProperty -Path $p -Name Flags -PropertyType DWord -Value 15

New-ItemProperty -Path $p -Name State -PropertyType DWord -Value 1

New-ItemProperty -Path $p -Name Version -PropertyType DWord -Value 2

最後にwsl.exeで確認を行なう。“-l -v”オプションで登録したディストリビューションが表示され、これが起動できれば成功である。起動テストは、“-d”オプションと各自のディストリビューション登録名を使う。

wsl.exe -l -v

wsl.exe -d TestWsl

WSL2のディストリビューションは、ローカルファイルシステムがvhdxファイルになっており、比較的簡単に扱うことができる。また、tar形式でバックアップすれば、実行中のWSLディストリビューションで簡単に一部のファイルを取り出すことが可能だ。

> Windows Subsystem for Linuxガイド 連載バックナンバー

https://news.mynavi.jp/tag/winsubsystem/