WSL2で dbus と WSLg が使えなかったのをどうにかする

変なやり方をするから苦労するんだ…

2年ぶりに WSL の新環境

Windows の作業環境を一新することになったので、いつものごとく WSL の環境を構築していた。

といっても、2年ぶりに一から環境構築するので以前とはちょっと状況が違う。

なんといってもまず、今は(毎回なんか問題踏んでる気もするが)WSL標準で systemd が使えるようになっている。いままで使っていた環境も代替実装からこれにマイグレーションしているのはいうまでもない。が、もともと対応していたわけではないところに入れているのは正しく動いているのか怖いものがある。

従来はDistrodを使用していたが、前述の理由からわざわざそんなことをする必要もなくなっており、メンテもされてなかったのでいろいろと検討した結果、今回はwsl2-distro-managerを使用して archlinux:latestのDockerイメージから 環境を構築してみることにした。そもそもArchをWSLで使うのは公式でサポートもされないどころか忌避されるようなものであるのは言うまでもない。一般的にはArchWSLとかを使うだろうか。

Dockerイメージベースと言っても、pacman等の一部の設定が変えられていることを除けば素のArchと何ら変わんないので、そのあたりの設定を変え、必要なパッケージを入れたりユーザーを作成したりwsl.confを設定したりすればだいたい普段の環境が出来上がる。もちろん boot.systemd=true

dbusが動かない

しかし、順調かに見えた環境構築に暗雲が立ち込める。dbusが使えないのである。systemd自体は動いているものの、ユーザーとしてsystemctlを叩こうもんならFailed to connect to bus: No such file or directoryなんておこられる。そう、dbusが起動していないのである。

そういえば最近Archのdbus daemonがdbus-brokerに変わった。まさか関係あるのだろうか…と思いながら従来の実装に入れ替えたりしてみたものの、何も変わらなかった。

ググっても出てくる情報は参考にならない。dbusがないだとか、起動しようとしていないだとかいうのである。そんなわけはない。systemctl status dbusをすればdeadになっているんだから。

それ単体のログを見てもよくわからなかったものの、debugConsoleでまわりのログをみているとあやしいものがあある。なんか文字化けしていたがよく読み解くと systemd-binfmt というサービスがコケている。

binfmt_misc はたとえばexeを自動的にmonoで開かせたりするのに使われるようなやつ。WSLでいえば、Windowsとの相互作用としてWindowsのexeを直接WSL内から実行できる機能そのものである。

proc/sys/fs/binfmt_misc/WSLInterop は先にインジェクトされてるとかで、当該サービスがコケてしまうことによってdbusくんも起動できない、みたいなことが起こっていたようである。

WSLでUbuntu22.04をインストールするとデフォルトでsystemdが利用されるというので、これを見てみると /etc/systemd/system/systemd-binfmt.service.d/00-wsl.confが以下の内容で存在している。

この設定により当該unitはWSL上では実行されなくなっているということであった。これを今回のArchにも持ち込んで再起動したところ、無事dbusが使用できるようになり、ユーザーからsystemctlが利用できるようになった。

なお、なぜか一旦解消したらもどしても問題なさそう。

WSLg が動か…ない?動いてる?

WSLgだって今時は特に何も設定しなければ使えるのが通例である。試しに gnome-text-editor を入れてみた。問題なく起動できる、やったね。

と思った矢先、konsole は起動できなかった。

何が違うのかというと、前者はWaylandで起動しているのに対し後者はX11だった。これらのランタイムファイルへのアクセス方法に違いがあり、waylandは /run/user/[uid]/wayland-[display number] を使用する。これは正しく/mnt/wslg/runtime-dir/wayland-0 へのsymlink となっていた。一方で、X11は /tmp/.X11-unix/X0 のようなファイルを使用する。しかし、今回このディレクトリは空になっていた。

X11なアプリだと:0が開けないと怒られる

この状況自体はWSLgにおいてよく発生するようである。みうぱよもはまっている

よくみかけるのはlnを張りなおすといった手段である。

しかし、これをするには当該ディレクトリを消してリンクを張るといったことを毎回しなければいけず、現実的ではない(unitにすればできるとはいえ)。

そもそも、/tmp/.X11-unix/proc/self/mountinfo のマウントプロパゲーションにより、systmdが勝手にマウントしているはずである。 systemctl status tmp-.X11\\x2dunix.mount をしてみるとactive (mounted)になっているのだ。

しかし、実際には空のディレクトリになっている。unmountしようとしてもmountしてないと怒られてしまう。これは、これが /tmp 以下にあることと深くかかわりがあるようだ。

/tmpはArchではtmpfsであるがこれは /usr/lib/systemd/system/tmp.mount によってマウントされるものである。systemdパッケージに含まれる。この前後関係がたまたま自動マウントのほうが先に行われた場合、当該ディレクトリは覆い隠されてしまうということであるようだ。(本当か?)

今回はとりあえずtmp.mountを無効化することでこれに対処してみた。

maskされたunitは/dev/nullにリンクするunitで隠され、無効化される。これで再起動したところ、X11のWSLgも問題なく動くようになった。尤も、マウントする順番が正しくなるように設定をなおすのが本来あるべき姿ではある気がする。今回は深掘りはしないので、誰か後は頼んだ。


まとめ

WSLの環境をいちから作ろうとすると結局よくわからない罠が多いので、先人の経験と知恵の積もった配布イメージを使うのが手っ取り早い事がよくわかった。binfmtはなんかに使えそうなのでまたちゃんとしらべたい。

コメントを残す