🪟

WSL2とArch Linux、systemdを添えて 2023/12

2023/12/24に公開

この記事は🎅GMOペパボエンジニア Advent Calendar 2023 - Adventar 22日目の記事です。

WSL2でSystemdが動くようになって久しいですが、新規にArch Linuxをインストールした環境(n=2)ではsystemdがinitialisingで止ってしまう事象がおきましたので、その解決も含めて手順を残しておきます。

参考

WSL等のバージョンは以下の通りです。

WSL バージョン: 2.0.14.0
カーネル バージョン: 5.15.133.1-1
WSLg バージョン: 1.0.59
MSRDC バージョン: 1.2.4677
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.25131.1002-220531-1700.rs-onecore-base2-hyp
Windows バージョン: 10.0.22631.2861

ベースイメージのダウンロードと再圧縮

WSL標準のディストリビューションでないものを使うには、wsl --importでファイルシステムのイメージをインポートする必要があります。

Arch Linuxが公式に配布しているベースイメージは、そのままではimportできないため一手間かける必要があります。そのためには、WSLのUbuntu等の環境があると便利なので、wsl --install等で用意しておきます。

ここでやることは2つです。

  • /etc/pacman.d/mirrorlistを編集する
  • ルートが/になるように圧縮しなおす

ベースのファイルシステムのダウンロード

https://www.archlinux.jp/download/ から適当なミラーを選択し、tar.gzをダウンロードします。インストールメディア(ISO)ではなくベースのファイルシステムであるtar.gzなので間違えないように。(archlinux-bootstrap-2023.12.01-x86_64.tar.gzといったファイル名になっているもの)

ダウンロードしたら、適当なディレクトリで展開します。

$ wget https://ftp.jaist.ac.jp/pub/Linux/ArchLinux/iso/2023.12.01/archlinux-bootstrap-2023.12.01-x86_64.tar.gz
.tar.zg
$ tar -zxvf archlinux-bootstrap-2023.12.01-x86_64.tar.gz

pacmanのmirrorlistを変更する

ベースイメージにはふつうのエディタが入っていないので、この時点でパッケージをインストールする際に使うミラーサーバーを設定しておくとよいです。

$ vim root.x86_64/etc/pacman.d/mirrorlist #適当なJapanのサーバのコメントアウトを外す

ここでもし忘れた場合は、wsl --import後に以下のような方法でリカバリーが可能です。シングルクオートにしないと変数が展開されて無になるので注意。

echo 'Server = https://mirrors.cat.net/archlinux/$repo/os/$arch' >> /etc/pacman.d/mirrorlist

tar.gzに再圧縮する

解答するとroot.x86+64というディレクトリができているので、この中に入ってからtar.gzに圧縮しなおします。

これによって、

  • root.x86_64/
    • usr
    • bin
    • ...

というような構造だったものが

  • /
    • usr
    • bin
    • ...

のようになります。この構造にすることでwsl --importができるようになります。

$ cd root.x86_64
$ tar -zcvf arch_bootstrap.tar.gz .

圧縮ファイルができたら /mnt/c/Users/your_name 等Windowsから見えるところに移動させておきます。

$ mv arch_bootstrap.tar.gz /mnt/c/Users/your_name/

wsl --import

作成したベースイメージをWSLにインポートします。第一引数はWSLへの登録名、第二引数がインストール先(ファイルシステムが置かれる場所)、第三引数がインポートするファイルです。

PS C:\Users\your_name> wsl --import arch C:\Users\your_name\wsl .\arch_bootstrap.tar.gz

インポートが終わったらwsl -lで確認しましょう。

PS C:\Users\your_name> wsl -l
Linux 用 Windows サブシステム ディストリビューション:
Ubuntu(既定)
arch

systemdを有効にする

作成した環境に入り、systemdを有効にします。最初の状態では有効になってないことを確認しましょう。

PS C:\Users\your_name> wsl -d arch

ここからはWSL内です。systemdはまだ起動していません。

[root@DESKTOP ~]# systemctl status
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

VM内のwsl.confにsystemdを使うための設定をします。これも最初にやっておけばよかったですね。

[root@DESKTOP ~]# echo -e "[boot]\nsystemd=true" > /etc/wsl.conf

PowerShellに戻り、WSLを再起動します。

PS C:\Users\your_name> wsl --shutdown

systemdがstartingのままになっている

WSLを再起動したと、systemctl statusをみるとStatestartingのまま止まっています。

[root@Desktop wsl]# systemctl status
Failed to dump process list for 'Desktop', ignoring: Input/output error
● Desktop
    State: starting
    Units: 283 loaded (incl. loaded aliases)
...

この状態でjournalctl -xb等でログを見てもあやしいところがありません。しかし、数分まってから再度statusを見ると、今度はdegradedとなり失敗しているunitがあることがわかります。

[root@Desktop wsl]# systemctl status
Failed to dump process list for 'Desktop', ignoring: Input/output error
● Desktop
    State: degraded
    Units: 286 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 1 units

再度journalctl -xb等でログを見ると、systemd-networkd-wait-online.serviceが失敗していることをみつけられます。

systemd[1]: systemd-networkd-wait-online.service: Failed with result 'exit-code'

原因のsystemd-networkdはdisableでよい

systemd-networkd-wait-online.servicesystemd-networkdからの依存で実行されるサービスですが、WSLで公式にサポートされているUbuntuでは同じような状況にはなっていません。ベースイメージを作成するときに利用したUbuntuをみてみると、なんとUbuntuではsystemd-networkdがdisableになっています。

たしかに、WSLのネットワークはWindows側でうまいことやってくれるので、systemd-networkdは不要なのかもしれません。ここまでわかってからissueをしらべてみると、systemd-networkd-wait-online.serviceに関する報告をいくつかみつけることができます。

例: WSL 2.0.1: systemd-logind logs session out after few minutes, purges /run/user/{uid} · Issue #10552 · microsoft/WSL

というわけで、systemd-networkdをdisableにして、WSLを再起動しましょう。

$ systemctl disable systemd-networkd

PowerShellでwsl --shutdownをしてから、再度WSLを開きsystemctl statusを実行するとrunningになっています。よかったですね。

[root@Desktop wsl]# systemctl status
Failed to dump process list for 'Desktop', ignoring: Input/output error
● Desktop
    State: running
    Units: 281 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 0 units
GitHubで編集を提案

Discussion