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

wsl2 x11 about

去年の暮に投稿した 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 で構いません。

wsl2 x11 2020 05 30 11 24 11

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

gnome-help

wsl2 x11 2020 05 30 11 25 59

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

参考資料