WSL2でX11 GUIがスリープ時に消える

去年の暮に投稿した Windows10 WSL のターミナル事情 記事内で、WSL1 でのシェルに VcXsrv+gnome-terminal を利用すると良いという記事を書きました。 状況はそれから少し変わっていて、

  • Windows Terminal がマトモになってきた(明るいテーマで常用するのはまだ難しい…)
  • 2020 年 5 月に WSL2 がリリースされ、WSL1 の方法で X11 転送を行うことができなくなった

という感じです。 WSL2 時代の GUI 環境の整え方をメモしておきます。

WSL2+VcXsrv の問題点

WSL1 ではカーネルが共有されていたので localhost 等のネットワーク空間も全てが共有されていたが、WSL2 では基本的にカーネルもネットワーク空間も共有されていません。Windows 上から WSL2 上のポートへのアクセスは localhost:80 等でアクセスできるが、逆の WSL2→Windows の接続には IP アドレスを指定する必要が有ります。

WSL1 では単に VcXsrv を起動して export DISPLAY=:0 するだけで X ウインドウが動作していました。これは localhost への接続を意味します。 WSL2 では export DISPLAY=172.20.0.1:0 などとする必要があります。IP アドレスは WSL2 側から見える Windows のアドレスを指定する必要があります。

この IP アドレスは、 /etc/resolv.conf から grep,awk を利用して抽出する事が可能です。 .profile 等で以下のようなシェルを実行すれば、今まで通り VcXsrv を動作させることが可能です。

# .profile
# ref: https://github.com/microsoft/WSL/issues/4106#issuecomment-501885675
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0

しかし、しばらく使えば今までと状況が異なることが分かると思います。 Windows をスリープすると X11 転送した GUI が消えます。

理由を想像すると簡単で、単に TCP セッションが終了しているのでしょう。Windows と WSL2 上でのドメインソケット等が提供されていない現時点で、直接的にこれを解消するのは難しそうです。

WSL2+Xpra でスリープ後もウインドウを維持

そこで利用したのが、Xpra です。 複数 OS で動作するスクリーン・X11 転送ソフトウェアです。 TCP セッションが切断されても GUI を再接続できるようです。GUI 版の tmux みたいな感じですかね。

リモート側の Linux マシン・ローカル側の Windows マシン、それぞれに Xpra をインストールします。

リモートの Linux マシンで Xpra サーバを起動します。 追加で DISPLAY 環境変数を指定し、以後起動される GUI アプリケーションの接続先を Xpra サーバに設定します。

xpra start --bind-tcp=0.0.0.0:10000 --daemon=yes :10000
export DISPLAY=:10000

Windows 上の Xpra を起動し、 Connect メニューより Linux 上で起動した Xpra サーバへ接続します。この時に指定するホスト名は localhost で構いません。

次にリモートの Linux マシンで、適当な GUI アプリケーションを起動します。

gnome-help

無事起動できました。試しにスリープ状態移行してもウインドウは維持されています。

参考資料