はじめに
この記事は WSL (WSLg) で 2024 年 11 月現在発生中の問題についての対処を記述しています。そのため将来的にこの対処が不要になる可能性もありますし、そうなることが期待されます。
現象
現在(2024年11月)時点で最新の WSL (WSLg) と、Wayland をディスプレイサーバに採用している Linux ディストリビューション(例: Ubuntu 24.04)で、Wayland が正しく動作していないために一部アプリが起動できなかったり、X11 にフォールバックするなどの不具合が発生しています。
- 手元での確認では Ubuntu 24.04 では発生しましたが、Ubuntu 22.04 では発生しませんでした
確認バージョン
- WSL
PS> wsl --version
WSL バージョン: 2.3.24.0
カーネル バージョン: 5.15.153.1-2
WSLg バージョン: 1.0.65
MSRDC バージョン: 1.2.5620
Direct3D バージョン: 1.611.1-81528511
DXCore バージョン: 10.0.26100.1-240331-1435.ge-release
Windows バージョン: 10.0.19045.5073
- WSLg
$ cat /mnt/wslg/versions.txt
WSLg ( x86_64 ): 1.0.65+Branch.main.Sha.25d8697d5049e1994baa6ba542f507347b608ad4
Built at: Wed Aug 14 21:11:14 UTC 2024
Mariner: VERSION="2.0.20240609"
DirectX-Headers:
mesa:
pulseaudio: 6f045ff0dca233a939a2aba815f84d177e294122
FreeRDP: c4030980b29322a9cb2190711a5fadeeeb8b6a33
weston: f227edd681479ec3cb2290a25d84d2d3462aebfa
- Linux は Ubuntu 24.04 を使用しています。他のディストリビューションでは一部コマンド等が異なる場合がありますので適宜読み替えてください
確認方法
簡単な方法としては、 wl-clipboard
(Ubuntu の場合)をインストールし、wl-copy
コマンドが動作するかどうかを確認するという方法があります。
wl-copy hoge
Wayland が正常に動作していれば何も出力せず終了し、Wayland のクリップボードに(上記の場合は)「hoge」という文字列が格納されます。WSL ではこれは Windows クリップボードと共有されるので、Windows 側のアプリで Ctrl-V などで貼り付けると先ほどコピーした「hoge」が入力されます。
Wayland が動作していないか異常な場合はエラーが出力されます。
原因
本来は XDG_RUNTIME_DIR
で指定された場所(たいていは /run/user/<userid>
)に Wayland のソケット(wayland-0
などのような名前)が作成されているはずです。
WSL の場合は /mnt/wslg/runtime-dir/wayland-0
などへのシンボリックリンクとして作成されますが、比較的新しいバージョンのディストリビューションではシンボリックリンクの作成ができておらず、ソケットが見つからないという状態になってしまいます。
暫定対処
単純にシンボリックリンクを張れば解決するのですが、手動で張っただけでは Linux (WSL) を再起動すると消えてしまうのでその都度張らなければいけません。そのため起動時に自動で張る方法を採ります。
ひとまずの対処として、以下の2種類の方法を挙げます。
1: 起動時にワンショットのユーザーサービスで設定する
-
自分のホームディレクトリに
.config/systemd/user
というディレクトリを作成し、その下に<適切な名前>.service
というファイルを作成します- 拡張子は
.service
で固定です。ファイル名は後で使いますので、どのようなサービスかわかる名前を付けてください。以降では仮にwsl-wayland-symlink.service
とします
- 拡張子は
-
以下のようなサービス定義を記述します
wsl-wayland-symlink.service[Unit] Description=Create Wayland symlinks for WSL After=default.target [Service] Type=oneshot ExecStart=/bin/sh -c 'USER_ID=$(id -u); find /mnt/wslg/runtime-dir -name "wayland-*" -type s -exec ln -sf {} /run/user/$USER_ID/ \;' [Install] WantedBy=default.target
- cat で一気にファイル作成と内容記述までやってしまってももちろんかまいません
- 内容としては、対象のシンボリックリンクを作成するサービスを起動時に1回だけ実行するというものです
-
サービスに登録して実行させます
systemctl --user daemon-reload systemctl --user enable wsl-wayland-symlink.service systemctl --user start wsl-wayland-symlink.service
- 実行後に
/run/user/<user id>
内に正しくシンボリックリンクが張られていることを確認してください
- 実行後に
-
Linux と WSL 自体の再起動(管理者 PowerShell で
wsl --shutdown
)をおこない、再起動後でも正しくシンボリックリンクが張られていることを確認します -
wl-copy
を試したり、動きに異常があった GUI アプリケーションを確認します
2: .bashrc
で設定する
簡易的な方法として .bashrc に追記する方法も記載しておきます。WSL のユースケースとしてターミナルは必ず起動すると思われますので、こちらもほとんどの場合は有効に動作します。
# いちばん簡単な記述
find "/mnt/wslg/runtime-dir/" -name 'wayland*' -exec basename {} \; | xargs -r -I {} ln -sf /mnt/wslg/runtime-dir/{} /run/user/$(id -u)/{}
# 念のため WSL 上で動いていることを確認してから実行する場合
if grep -qEi "(Microsoft|WSL)" /proc/version &>/dev/null; then
find "/mnt/wslg/runtime-dir/" -name 'wayland*' -exec basename {} \; | xargs -r -I {} ln -sf /mnt/wslg/runtime-dir/{} /run/user/$(id -u)/{}
fi
補足
参考資料には、「systemd-tempfiles の仕組みを利用して起動時にシンボリックリンクを張る」という例も挙げられていたのですが、以下の要因より対処案から除外しました。
- そもそもその機能が正常に働かない状況に陥っているようであること
- ユーザー側で動作させれば同じようにシンボリックリンクが張れるのだが、そのためには結局ユーザーサービスの設定が必要になること
- ソケットの名称の末尾の数字が変わる可能性があること