諸々の理由によりWindowsな皆様こんにちは。Bash on Ubuntu on Windows使ってますか?私はBash on openSUSE on Windows派です。
Windows10の10月17日予定のアップデートFall Creators Update(1709)からBash on WindowsことWSLことWindows Subsystem for Linuxが正式版になり、あわせてUbuntuだけでなくopenSUSE/SLES、また予定ではFedoraなどディストリビューションを選ぶこともできるようになり、たいへん導入しやすくなりました。
さて、このWSLは単体でもコンソールとしては優秀ですが、X Window Serverと組み合わせるとおおよそLinuxデスクトップっぽくなってたいへん素敵です。素敵度合いをアピールするために、これ見よがしなスクリーンショットを用意しておきました。
どれがLinuxアプリでどれがWindowsアプリかわからない…といいんですが。この記事はそんなWSL + X Windowをもう少しだけチューニングすることで、Linux GUI環境をストレスフリーに使うためのtweak記事です。
WSLとX Window Serverの組み合わせ自体の方法については、すでに先達の方々がおられるので、そちらをご覧ください。(だいたい原理も何も知っているのでもう言わんでよかって人のためにopenSUSE on WSLでのLXDE導入方法も書いておきました。→ページ内ジャンプ)
なお、X Window ServerはVcXsrv、デスクトップ環境はLXDEで、スクリーンショットもそれに準じています。環境に応じて随時読み替えてください。ちなみに、Xmingは最新版(寄付版)を持っていないのであれば、VcXSrvの方がだいたいすべての面でいいです。
フォントの設定
X Window Systemとフォントの関係はややこしいのですが、今どきはX Windowで表示されるフォントはLinux側のフォントです。Linux上のフォントは昔に比べればだいぶ綺麗になりましたが、Windowsアプリと一緒に使うと明らかな違和感があります。せっかくWindowsで使用しているので、Windowsフォントに合わせましょう。Windowsのフォントフォルダを丸ごとLinuxから見えるようにします。
# sudo ln -s /mnt/c/Windows/Fonts /usr/share/fonts/windows
# sudo fc-cache -fv
これでWindows10フォントがLinuxから選べるようになったと思います。
フォントが選べるようになったので、システムのルックアンドフィールをWindows10に合わせると、Linuxアプリの違和感がかなり軽減されます。Windows10のデフォルトは、Yu Gothic UI
のRegular
でサイズは10
か11
ぐらいだと思います。
高DPI環境への対応
フォントの設定からわかるように、X WindowのフォントレンダリングはLinux側のフォントレンダリングです。Windows10は高解像度環境(HiDPI環境)でウィンドウを自動スケールしますが、Linuxから送られてきているのはレンダリング後の単なるビットマップなので、フォントが単に引き伸ばされてボケてしまいます。Windows側のスケーリングを無効化してLinux側でスケールしましょう。
VcXsrvのスケーリングを無効にする
Linuxでスケーリングする
XmingやVcXsrvでは-dpi
でスケーリングを起動時に指定することができます。~/.Xresources
ファイルでXft.dpi
パラメータで指定することもできるようです。Windows10の100%値は96
のようです。ただし、微妙な差異により(Windowsのシステムフォントサイズが10.5になってるとか?)、計算通りにスケーリングしても、Windows10と合わなかったりするので、環境ごとに調整してみてください。
bash.exe画面を表示せずに任意のLinuxプログラムを起動する
X Windowのアプリケーションを起動するという点においては、bash
は不要です。できることならWindowsから直接的に必要なアプリケーションか、あるいはLXDEにおけるlxpanel
のような、タスクバー(および設定メニュー込みのアプリケーションランチャー)プログラムを起動したいはずです。
しかし、この記事を書いている時点では、bash
抜きにWSLを起動する公式の手法はありません。WSLの起動は、bash.exe
の実行とほぼ同義ですが、bash.exe
は必ずコンソールを必要とし、bash.exe
から起動されたバックグラウンドプロセスは、bash.exe
を落とした時点で終了してしまいます。
すると、たとえば「ファイル名を指定して実行」からbash -lc lxpanel
などと実行しても、こんな画面が残ってしまいます。
この画面を消します。
WSHスクリプト
単純に考えると、lxpanel
を実行した後のbash.exe
の画面をhiddenにしてくれればいいのです。子プロセスの画面を隠してくれるフリーウェアも探せばありそうですが、Windows標準のWSHスクリプトで簡単に作れそうなので作ります。
var shell = new ActiveXObject("WScript.Shell");
var args = WScript.Arguments;
var cmd = [];
var i;
for (i = 0; i < args.length; i++) {
cmd.push(args(i))
}
shell.Run('bash -lc "' + cmd.join(' ') + '"', 0, true);
// bash -lc 'xxxx'をウィンドウなし(0)で、同期的(true)に実行します
// ※ここは最初、次のように書いていましたが、Windows10の何かの更新により、
// ''と""で解釈が変わるようになり、下のコードでは動かなくなったようです
// shell.Run("bash -lc '" + cmd.join(' ') + "'", 0, true);
これで、X Window Serverが立ち上がってさえいれば、「ファイル名を指定して実行」からwscript run-linux.js xterm
などとすることで、あたかもbash
を介在しなかったかのようにLinuxプログラムを起動することができます。また、Linuxプログラムが終了すると自動的にbash.exe
も終了します。
XLaunchファイルの設定
上記のWSHスクリプトは起動前にX Window Serverが立ち上がっていなければなりません。それはそれで面倒なので、同時に立ち上げる方法を考えます。
単純にはスクリプトでVcXSrvを前もって起動するようにするのがよいのですが、実はXmingやVcXsrvの起動設定ファイル*.xlaunch
ファイルは、X Window Server起動後にローカルなプログラムを起動するように構成できます。本来何に使うのが正しいのかよくわからない(テスト用?)機能ですが、ここからWSHスクリプトを実行可能です。簡単のため、先ほどのWSHスクリプトファイルrun-linux.js
はC:\\Program Files\VcXsrv
に入れておきます。
<?xml version="1.0" encoding="UTF-8"?>
<XLaunch
WindowMode="MultiWindow" ClientMode="StartProgram"
LocalClient="True" Display="-1"
LocalProgram="wscript run-linux.js lxpanel"
RemoteProgram="" RemotePassword="" PrivateKey="" RemoteHost=""
RemoteUser="" XDMCPHost="" XDMCPBroadcast="False" XDMCPIndirect="False"
Clipboard="True" ClipboardPrimary="True" ExtraParams="-dpi 96" Wgl="True"
DisableAC="False" XDMCPTerminate="False"
/>
これでダブルクリックするだけで、いつでもlxpanelが立ち上がるようになりました。
ただし、このままではlxpanelやそこから起動するシェルのカレントディレクトリが/mnt/c/Program Files/VcXsrv
になってしまいます。それが困る場合はLocalProgram="wscript run-linux.js cd; lxpanel"
などとします。
またlxpanelはlxpanel --profile LXDE
で起動したほうが、見た目がopenSUSEっぽくなります。お好みで。
ログアウト
lxpanelのほうでも、ログアウトに備えておきます。ログアウト時にlxpanelctl exit
を実行するようにします。この設定は、デスクトップ環境によっては不要なのかもしれません。これによりログアウトすると、無事にプロセスが死に、自動的にVcXsrvも落ちます。
※Windows 10 April 2018 Update(1803)から、ログアウトしてもデーモン化されたプロセスは生存できるようになったため、ログアウトしてもWSL環境が閉じられるとは限らないので注意してください。
dbusを設定するしない
※ここにはdbusの設定がいる風の説明がありましたが、時代遅れの真っ赤なウソでした。今のWSLではdbusは特に設定なしで動きます。お詫びして訂正いたします。
おわり
WSLをストレスフリーに使う設定のお話でした。
おまけ
XLaunchだけでできる?
ところで、XLaunchですが、wscriptが実行できるのと同じように、ここからダイレクトにbash -lc lxpanel
とか実行することも可能です。XLaunchが起動したコマンドはただちに非表示にされるので、これでもうまくいきそうな気がします。ところが私の環境では、この状態では起動時によくわからない入力警告メッセージが出て、ログアウト時にもきれいに終了しない状態になってしまいました。原因を追いかけてちゃんと設定するとXLaunchだけでいい感じにできるのかもしれません。
X Windowいらない?
LXTerminalのようなLinuxコンソール的な端末環境が欲しいだけであれば、Windowsにcmd.exeの代替となる端末環境を入れるのがいいみたいです。
Javaでもスケーリングする(高DPI環境用)
たぶんWSL環境によらない話だと思いますが、Linux Javaアプリ(IntelliJなどのJetBrainツールやEclipse)をスケーリングするときはさらに大変なようです。PyCharmとEclipseを試しましたが、-dpi
設定は考慮してくれませんでした。対応方法をメモとして残しておきます。
まず実行用のJVMはJava9にしてGTK3で動くようにしてください。(Java9でJEP 283: Enable GTK 3 on Linuxがリリースされたためです)
GTK3は環境変数でスケーリングできます。(Using GTK+ on the X Window System)
関連する環境変数が二つあり、GDK_SCALE
は整数しか指定できませんが全てのオブジェクトを拡大できるもので、GDK_DPI_SCALE
は小数点付き数値が指定可能でフォントサイズを拡大(縮小も)できるもののようです。一般的にはGDK_SCALE
で大きくしつつ、GDK_DPI_SCALE
で文字だけ縮小するような使い方をするようですが、試行錯誤の結果、次のような指定でどうにかなりました。
# GDK_SCALE=2 ./pycharm.sh
# GDK_DPI_SCALE=2 ./eclipse
調べた限り、どうしてデフォルトでスケーリングしてくれないのか、どうしてこれである程度うまくいくのかさっぱりわからなかったので、環境依存性がどの程度あるのかもわからないのですが、困ったらとりあえずこの2つの環境変数を調整したらどうにかなるんじゃないでしょうか。たぶん。
openSUSE on WSLでLXDEをセットアップ
だいぶん適当なので、余計なものも入るかもしれませんがご愛嬌で。
> echo export DISPLAY=localhost:0.0 >> ~/.bashrc
> echo export LANG=ja_JP.utf-8 >> ~/.bashrc
> su -
Password:
# zypper install MozillaFirefox lxde-common lxpanel-lang lxterminal-lang lxcc yast2-x11 yast2-sudyast2-trans-ja gtk2-theme-* gnome-colors-icon-theme pcmanfm pcmanfm-lang yast2-control-center lxappearance-lang lxappearance-obconf-lang gnome-icon-theme-* yast2-metapackage-handler man-pages-ja gsettings-backend-dconf
ネットワークにつながらない?
私の環境では何かのタイミングで、/etc/resolv.conf
が謎のバイナリになりネットワークが不通になることがありました。WSL環境のresolv.conf
はWSL起動時にWSLが生成してくれる、ということになっていますが、何らかの都合で破損したり生成できなくなることがあるようです。このときは、一度resolv.conf
を削除して、/etc/wsl.conf
を作ってみたりすると治るかもしれません。