(自分はOmarchyに全く興味ないので、タイトルに入れてるのはこう書いといた方が見てくれる人居るかなーという雑な理由によるもので、Omarchyの話はほぼありません。)
最近のモダンなWaylandデスクトップの裏側にはuwsm - Universal Wayland Session Managerというものが居ることが多いんですが、これが何なのかとても分かりにくいし、日本語で説明されてる文書がほとんど無かったのでブログにまとめてみることにしました。 多分、需要はほぼ無いと思いますが、自分の理解を一回整理しておくメモでもあります。
Waylandデスクトップ
モダンなLinuxデスクトップは大抵Waylandというディスプレイサーバーを利用する様になっていて、これは今迄Linuxで使われていたディスプレイサーバーのXを置き換えるものです。 パフォーマンスの向上、GPU活用、セキュリティ上の懸念の解消、メンテナンス性を高める、などの目的で置き換えが進んでいます。
ただ、通信プロトコルの策定はそんなにスムーズにいってない様で、結構unstableという名前がついたプロトコルに依存して現状動いているといった感じです。
Waylandのデスクトップは今迄のXの仕組みとは関係が無いところで動くので、uwsmを利用しない場合は、startxみたいなコマンドは使わず直接ウインドウマネージャーのコマンドを実行して起動します。
GnomeとかPlasmaみたいなフルスタックのデスクトップ環境を利用している場合は、そこに任せれば良いんですが、世の中にはミニマルなタイル方ウインドウマネージャーを利用したい派閥がそれなりに居ます。
自分はHyprlandユーザーだし、OmarchyもHyprlandを利用する様になってる様です。i3の設定とかなり互換性があるswayも結構人気があります。
Wayland起動時の問題とそれを解決するuwsm
startxとそれに付随するX関係のシェルスクリプト読み込みが発生しないので、普通にコマンドを使って直接起動すると、今迄Xで動作していた自動起動とかGUI向けの環境変数の設定(XMODIFIERS=@im=fcitxみたいなIMの利用設定とか)を読み込んでくれません。
素朴な解決策としては、ラッパーのシェルスクリプトを書いてそこで環境変数を設定してからコマンドを起動すれば良いんですが、それだと管理しづらいし単純に面倒臭い。特に自動起動はダルい。
という訳で、uwsmの出番になります。
uwsmはWaylandデスクトップの起動コマンドをAdhocなsystemdのunitにラップして起動することによって、GUIのための環境変数を登録し自動起動して欲しいものを全てsystemdで管理可能にします。
uwsmの設定方法はUniversal Wayland Session Manager - ArchWikiを参考にしてみてください。 自分はReGreetというgreetdのGUIフロントエンドから起動する様に設定してみました。
uwsmの動作
uwsmはざっくり以下のことを実施する。
- ウインドウマネージャーのコマンドを実行するためのsystemdのunitファイルを生成する
- unitファイルの依存関係を利用して、prehook posthookを仕込めるsystemdのtargetに対する依存関係を設定する
- systemdの依存関係によってwayland-session@%i.targetがアクティブになり、それを経由してgraphical-session.targetがアクティブになる様に依存関係が構成される
- XDG Autostartの管理対象のディレクトリにあるdesktopエントリを起動するunitファイルを動的に生成する
- このunitファイルはgraphical-session.targetに依存しており、graphical-session.targetがアクティブになった後に起動される
- uwsm用のemv設定ファイルに書かれた環境変数を設定した上でウインドウマネージャーのsystemd unitが起動し、環境変数がdbusのAPIを経由してsystemdに登録される
細かい順番は違うかもしれない。
こうすることで、systemdのunitの依存関係にgraphical-session.targetを設定しておけば、uwsmによってウインドウマネージャーが起動した時に必要なコマンドをsystemdが自動的に起動してくれる様になる。
これでXDG Autostartに登録される旧来のアプリも自動起動が効くし、新しいwayland向けのアプリであればgraphical-session.targetに依存したsystemdのunitファイルをセットで提供してくれるものも多くあるので、systemctl --user enableで自動起動を有効にできる。
例えば、Wayland環境でよく利用されているタスクバーのwaybarで提供されているsystemdのunitファイルは以下の様になり、利用しているウインドウマネージャーの設定方法に関わらずsystemctl --user enable waybar.serviceで自動起動が有効になる。
# /usr/lib/systemd/user/waybar.service [Unit] Description=Highly customizable Wayland bar for Sway and Wlroots based compositors Documentation=https://github.com/Alexays/Waybar/wiki/ PartOf=graphical-session.target After=graphical-session.target Requisite=graphical-session.target [Service] ExecStart=/usr/bin/waybar ExecReload=kill -SIGUSR2 $MAINPID Restart=on-failure [Install] WantedBy=graphical-session.target
ウインドウマネージャーを終了する時もsystemdが依存関係を見て自動的にプロセスを落としてくれる様になる。
uwsm利用下でのアプリ起動
もう一つの重要な機能として、手動で何らかのアプリケーションを起動する時にそれをsystemdの管理下に置く機能がある。
uwsm app -- <command or desktop entry>としてコマンドを実行すると、そのコマンドをsystemdで管理しているslice下に紐付けてくれる。
systemdはデフォルトでapp.slice, background.slice, session.sliceという3つのsliceを提供していて、これはcgroupのリソース管理と紐付けられている。デフォルトではbackground.sliceだけCPUWeightが30に設定されており、CPUリソースを食い合った時の優先度が下がる様になっている。
uwsmはこれを拡張してapp-graphical.slice, background-graphical.slice, session-graphical.sliceというsliceを提供している。sliceは-区切りで階層構造が表現できるらしい。
これらのsliceはこんな感じの中身になっている。
# /usr/lib/systemd/user/app-graphical.slice [Unit] Description=User Graphical Application Slice Documentation=man:uwsm(1) man:systemd.special(7) PartOf=graphical-session.target After=graphical-session.target Conflicts=wayland-session-shutdown.target Before=wayland-session-shutdown.target
このsliceに紐付いているプロセスはgraphical-session.targetの一部で、wayland-session-shutdownのtargetがアクティブになったら終了しますよって感じの内容になる。ウインドウマネージャー起動後にランチャーなどで起動したアプリをsliceに紐付けることで、cgroupの設定を上書きしたり、wayland sessionのshutdown時に自動的にプロセスをちゃんと終了する、といった動作が可能になる。
uwsmはこんな感じで、コマンドをラップしてsystemdのunitやscopeに変換し、targetに対する依存関係を利用することでデスクトップ環境起動時の自動起動や終了時のプロセス停止を安全に行う方法を提供してくれる。
最初、何故こういうものが必要になるのか良く分かっていなかったのですが、ちゃんと設定すると環境変数や自動起動の管理が大分楽になることが分かったし、ウインドウマネージャーが落ちた時にゴミプロセスを残さずに済むことが分かりました。(まあ、後者の状況になったら大抵はrebootかけますが……)