「Systemd/ユーザー」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
 
(4人の利用者による、間の16版が非表示)
1行目: 1行目:
 
{{Lowercase title}}
 
{{Lowercase title}}
[[Category:デーモンとシステムサービス]]
+
[[Category:システム管理]]
[[Category:ブートプロセス]]
 
 
[[en:Systemd/User]]
 
[[en:Systemd/User]]
 
[[es:Systemd/User]]
 
[[es:Systemd/User]]
 
[[fr:Systemd/utilisateur]]
 
[[fr:Systemd/utilisateur]]
 
[[it:Systemd/User]]
 
[[it:Systemd/User]]
[[zh-CN:Systemd/User]]
+
[[ru:Systemd/User]]
  +
[[zh-hans:Systemd/User]]
 
{{Related articles start}}
 
{{Related articles start}}
 
{{Related|systemd}}
 
{{Related|systemd}}
{{Related|仮想端末に自動ログイン}}
+
{{Related|仮想コンソールに自動ログイン}}
 
{{Related|ログイン時に X を起動}}
 
{{Related|ログイン時に X を起動}}
 
{{Related articles end}}
 
{{Related articles end}}
17行目: 17行目:
 
== 利用方法 ==
 
== 利用方法 ==
   
ユーザーがログインを行うと、systemd は自動的にユーザーサービスを管理する {{ic|systemd --user}} インスタンスを起動します。このプロセスは、そのユーザーにセッションが残っているかぎり生存し、ユーザーの最後のセッションが閉じられた時に終了します。[[#systemd のユーザーインスタンスを自動起動|systemd のユーザーインスタンスを自動起動]]している場合、インスタンスはブート時に起動し、終了しません。デフォルトではユーザーサービスは何も実行されません。ユーザーサービスを使うことで、ソケットアクティベーションやタイマー、システムの依存関係や cgroups によるプロセスの制限など、systemd の恩恵を最大限活用して、デーモンや自動化されたタスクを実行できます。ユーザーユニットはシステムサービスと同じように以下のディレクトリに配置されます (優先度が低い順):
+
ユーザーがログインを行うと、systemd は自動的にユーザーサービスを管理する {{ic|systemd --user}} インスタンスを起動します。このプロセスは、そのユーザーにセッションが残っているかぎり生存し、ユーザーの最後のセッションが閉じられた時に終了します。[[#systemd のユーザーインスタンスを自動起動|systemd のユーザーインスタンスを自動起動]]している場合、インスタンスはブート時に起動し、終了しません。ユーザーサービスを使うことで、ソケットアクティベーションやタイマー、システムの依存関係や cgroups によるプロセスの制限など、systemd の恩恵を最大限活用して、デーモンや自動化されたタスクを実行できます。
  +
  +
ユーザーユニットはシステムサービスと同じように以下のディレクトリに配置されます (優先度が低い順):
   
 
* {{ic|/usr/lib/systemd/user/}}: インストールしたパッケージに含まれているサービス
 
* {{ic|/usr/lib/systemd/user/}}: インストールしたパッケージに含まれているサービス
  +
* {{ic|~/.local/share/systemd/user/}}: ホームディレクトリにインストールしたパッケージのユニット
 
* {{ic|/etc/systemd/user/}}: システムの管理者が配置する、全てのユーザーが使えるユーザーサービス
 
* {{ic|/etc/systemd/user/}}: システムの管理者が配置する、全てのユーザーが使えるユーザーサービス
 
* {{ic|~/.config/systemd/user/}}: ユーザーが配置する、そのユーザーのサービス
 
* {{ic|~/.config/systemd/user/}}: ユーザーが配置する、そのユーザーのサービス
26行目: 29行目:
   
 
{{Note|
 
{{Note|
* {{ic|systemd --user}} インスタンスはユーザーごとのプロセスであり、セッションごとのプロセスではないので注意してください。ソケットやステートファイルなどのユーザーサービスによって扱われるリソースはセッションごとではなくユーザーごとに割り振られる (ユーザーのホームディレクトリ上に存在する) というのが原則です。つまりユーザーサービスは全てセッションとは関係なく動作します。結果として、セッションの中で実行する必要があるプログラムはユーザーサービスの中で壊れてしまう可能性があります。systemd のユーザーセッションの扱い方は流動的であり確定していません。[https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] や [http://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html] が今後どうなるかのヒントになるでしょう。
+
* バージョン206から、{{ic|systemd --user}} インスタンスはユーザーごとのプロセスであり、セッションごとのプロセスではないので注意してください。ソケットやステートファイルなどのユーザーサービスによって扱われるリソースはセッションごとではなくユーザーごとに割り振られる (ユーザーのホームディレクトリ上に存在する) というのが原則です。つまりユーザーサービスは全てセッションとは関係なく動作します。結果として、セッションの中で実行する必要があるプログラムはユーザーサービスの中で壊れてしまう可能性があります。systemd のユーザーセッションの扱い方は流動的であり確定していません。[https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] や [https://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html] が今後どうなるかのヒントになるでしょう。
 
* {{ic|systemd --user}} は {{ic|systemd --system}} プロセスとは別のプロセスを起動します。ユーザーユニットからシステムユニットに依存したり参照することはできません。
 
* {{ic|systemd --user}} は {{ic|systemd --system}} プロセスとは別のプロセスを起動します。ユーザーユニットからシステムユニットに依存したり参照することはできません。
 
}}
 
}}
34行目: 37行目:
 
Systemd のユーザーインスタンスはログイン時に自動で起動します。正しく起動していることを確認するには、次のコマンドを使います: {{ic|systemctl --user status}}。
 
Systemd のユーザーインスタンスはログイン時に自動で起動します。正しく起動していることを確認するには、次のコマンドを使います: {{ic|systemctl --user status}}。
   
  +
ユーザーサービスは全て {{ic|~/.config/systemd/user/}} に配置してください。ログイン時にサービスを実行したい場合は、自動実行したいサービスごとに {{ic|systemctl --user enable ''service''}} を実行してください。
{{Note|systemd のユーザーインスタンスが自動で実行されない場合 {{ic|/etc/pam.d/system-login}} ファイルを確認してください。このファイルには {{ic|-session optional pam_systemd.so}} というような行が含まれていなくてはなりません。''.pacnew'' ファイルが存在していないかチェックしてください。}}
 
   
  +
=== D-Bus ===
ユーザーサービスは全て {{ic|~/.config/systemd/user}} に配置してください。ログイン時にサービスを実行したい場合は、自動実行したいサービスごとに {{ic|systemctl --user enable ''service''}} を実行してください。
 
   
  +
プログラムによっては [[D-Bus]] ユーザーメッセージバスを必要とすることがあります。D-Bus は伝統的に {{ic|dbus-launch}} によってデスクトップ環境の起動時に実行されていましたが、バージョン226から、systemd がユーザーのメッセージバスを管理するようになりました [https://www.archlinux.jp/news/d-bus-now-launches-user-buses/]。{{ic|dbus.socket}} や {{ic|dbus.service}} のユーザーユニットによって全てのセッションでユーザーごとに ''dbus-daemon'' が起動します。
{{Note|バージョン 206 から、systemd のユーザーインスタンスの仕組みは変更されています。現在、デフォルトで {{ic|pam_systemd.so}} モジュールがユーザーインスタンスを起動します。手動で起動する必要はありません。{{AUR|user-session-units}} の {{ic|user-session@.service}} は廃止されました。この変更によって {{ic|systemd --user}} はユーザーセッションの外で実行されます。}}
 
   
  +
{{Note|{{ic|/etc/systemd/user/}} や {{ic|~/.config/systemd/user/}} に手動でユニットを作成していた場合は、削除してもかまいません。}}
=== D-Bus ===
 
   
  +
=== 環境変数 ===
プログラムによっては [[D-Bus]] ユーザーメッセージバスを必要とすることがあります。D-Bus は伝統的に {{ic|dbus-launch}} によってデスクトップ環境の起動時に実行されています。しかしながら、D-Bus に依存するプログラムを systemd のユーザーサービスとして使う場合、依存関係を解決するために D-Bus サーバーも systemd サービスとして実行する必要が出てきます。
 
   
  +
systemd のユーザーインスタンスは {{ic|.bashrc}} などに設定された[[環境変数]]を全く継承しません。systemd インスタンスに環境変数を設定する方法は複数存在します:
{{Note|将来 systemd から kdbus への移行がされることで、systemd はシステムとユーザーのメッセージバスのマネージャになります。}}
 
   
  +
# {{ic|$HOME}} ディレクトリが存在するユーザーの場合、{{ic|~/.config/environment.d/}} ディレクトリに {{ic|1=NAME=VAL}} という形式で環境変数を記述した ''.conf'' ファイルを作成する。ユーザーのユニットファイルにのみ影響します。詳しくは {{man|5|environment.d}} を見てください。
D-Bus を systemd サービスとして設定するには、以下を行う必要があります:
 
  +
# {{ic|/etc/systemd/user.conf}} で {{ic|DefaultEnvironment}} オプションを使う。全てのユーザーユニットに影響します。
  +
# {{ic|/etc/systemd/system/user@.service.d/}} に設定ファイルを追加する。全てのユーザーユニットに影響します。[[#サービス例]]を参照。
  +
# 適宜、{{ic|systemctl --user set-environment}} や {{ic|systemctl --user import-environment}} を使う。環境変数を設定した後に起動したユーザーユニットには影響しますが、既に起動しているユニットには影響しません。
  +
# [[D-Bus]] の {{ic|dbus-update-activation-environment --systemd --all}} コマンドを使う。{{ic|systemctl --user import-environment}} と同じ効果があり、D-Bus セッションに適用されます。コマンドはシェルの初期化ファイルの末尾に追加できます。
  +
# ユーザー環境全体の環境変数は systemd のジェネレータによって読み込まれる {{ic|environment.d}} ディレクトリを使用できます。詳しくは {{man|5|environment.d}} を参照。
  +
# 環境生成スクリプトを記述することでユーザーごとに環境変数を生成することもできます。ユーザーごとに環境変数を設定する必要は役に立つでしょう (XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS など)。{{man|7|systemd.environment-generator}} を見てください。
   
  +
設定するべき変数としては {{ic|DISPLAY}} や {{ic|PATH}} などが考えられます。
1. dbus サーバーのサービスユニットとソケットユニットを {{ic|/etc/systemd/user/}} に追加:
 
   
  +
==== サービス例 ====
{{hc|/etc/systemd/user/dbus.socket|<nowiki>
 
  +
[[Systemd#ドロップインファイル|ドロップイン]]ディレクトリ {{ic|/etc/systemd/system/user@.service.d/}} を作成して、その中に拡張子が {{ic|.conf}} のファイルを作成します (例: {{ic|local.conf}}):
[Unit]
 
  +
{{hc|/etc/systemd/system/user@.service.d/local.conf|2=
Description=D-Bus User Message Bus Socket
 
  +
[Service]
  +
Environment="PATH=/usr/lib/ccache/bin:/usr/local/bin:/usr/bin:/bin"
  +
Environment="EDITOR=nano -c"
  +
Environment="BROWSER=firefox"
  +
Environment="NO_AT_BRIDGE=1"
  +
}}
   
  +
==== DISPLAY と XAUTHORITY ====
[Socket]
 
ListenStream=%t/bus
 
   
  +
{{ic|DISPLAY}} は X アプリケーションがどのディスプレイを使えばいいのか知るために使用されます。{{ic|XAUTHORITY}} はユーザーの {{ic|.Xauthority}} ファイルのパスと、X サーバーにアクセスするのに必要な cookie を指定します。systemd ユニットから X アプリケーションを起動する場合、これらの変数を設定する必要があります。[https://github.com/systemd/systemd/blob/v219/NEWS#L194 バージョン 219] から、セッションが開始したときに {{ic|DISPLAY}} と {{ic|XAUTHORITY}} を {{ic|systemd --user}} デーモンの環境にアップロードする X11 セッションアプレット {{ic|/etc/X11/xinit/xinitrc.d/50-systemd-user.sh}} が systemd に付属するようになりました。これによって、X を標準の方法で起動しているかぎり、ユーザーサービスは {{ic|DISPLAY}} や {{ic|XAUTHORITY}} を使用することができるようになっています。
[Install]
 
WantedBy=sockets.target
 
Also=dbus.service
 
</nowiki>}}
 
   
  +
==== PATH ====
{{hc|/etc/systemd/user/dbus.service|<nowiki>
 
[Unit]
 
Description=D-Bus User Message Bus
 
Documentation=man:dbus-daemon(1)
 
Requires=dbus.socket
 
   
  +
{{ic|PATH}} 変数を {{ic|.bashrc}} や {{ic|.bash_profile}} で設定しても systemd では使うことができません。{{ic|PATH}} をカスタマイズしており、それを利用するアプリケーションを systemd ユニットから起動する予定があるなら、systemd 環境に {{ic|PATH}} を設定する必要があります。{{ic|PATH}} を {{ic|.bash_profile}} に設定している場合、以下を {{ic|PATH}} 変数を設定した後の {{ic|.bash_profile}} に追加するのが systemd で {{ic|PATH}} を設定する一番簡単な方法です:
[Service]
 
ExecStart=/usr/bin/dbus-daemon --session --address=systemd: --nofork --nopidfile --systemd-activation
 
ExecReload=/usr/bin/dbus-send --print-reply --session --type=method_call --dest=org.freedesktop.DBus / org.freedesktop.DBus.ReloadConfig
 
   
  +
{{hc|~/.bash_profile|<nowiki>
[Install]
 
  +
systemctl --user import-environment PATH
Also=dbus.socket
 
 
</nowiki>}}
 
</nowiki>}}
   
  +
==== pam_environment ====
2. 環境変数 {{ic|DBUS_SESSION_BUS_ADDRESS}} を設定。以下のファイルを作成して、{{ic|user@.service}} の設定ファイルを使うことで設定できます:
 
   
  +
{{ic|pam_env.so}} モジュールを利用することで環境変数を設定できます。{{ic|~/.pam_environment}} ファイルを以下のように作成してください:
{{hc|/etc/systemd/system/user@.service.d/dbus.conf|<nowiki>
 
[Service]
 
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/bus
 
</nowiki>}}
 
   
  +
{{hc|~/.pam_environment|2=
{{Note|systemd 209 以前は {{ic|DBUS_SESSION_BUS_ADDRESS}} は上流の {{ic|user@.service}} ユニットで設定されていました。現在は異なります。kdbus への移行が完了したら、{{ic|pam_systemd.so}} によって変数が設定されるようになるから、というのが理由のようです。}}
 
  +
XDG_CONFIG_HOME DEFAULT=@{HOME}/.local/config
  +
XDG_DATA_HOME DEFAULT=@{HOME}/.local/data
  +
}}
   
  +
{{ic|.pam_environment}} ファイルの構文に関する詳細は[[環境変数#pam_env を使う]]を見てください。{{ic|systemctl --user show-environment}} コマンドを実行することで設定が上手くいっているか確認できます:
3. root で以下を実行してソケットを有効化:
 
   
# systemctl --global enable dbus.socket
+
{{hc|$ systemctl --user show-environment|2=
  +
...
  +
XDG_CONFIG_HOME=/home/''user''/.local/config
  +
XDG_DATA_HOME=/home/''user''/.local/data
  +
...
  +
}}
   
  +
=== systemd のユーザーインスタンスを自動起動 ===
=== 環境変数 ===
 
   
  +
systemd のユーザーインスタンスはデフォルトでユーザーの最初のログイン時に実行され、ユーザーのセッションが閉じられた時に終了します。しかしながら、ブートした直後にインスタンスを起動して、セッションが閉じられてもユーザーインスタンスを実行し続ける方が、例えばセッションが開いてない時もユーザープロセスを実行したいときなどには便利です。linger を利用してこれを行います。特定のユーザーで linger を有効にするには以下のコマンドを使用:
systemd のユーザーインスタンスは {{ic|.bashrc}} などに設定された[[環境変数]]を全く継承しません。systemd インスタンスに環境変数を設定する方法は3つあります:
 
   
  +
# loginctl enable-linger ''username''
# {{ic|/etc/systemd/user.conf}} で {{ic|DefaultEnvironment}} オプションを使う。全てのユーザーユニットに影響します。
 
# {{ic|/etc/systemd/system/user@.service.d/}} に設定ファイルを追加する。全てのユーザーユニットに影響します。
 
# 適宜、{{ic|systemctl --user set-environment}} や {{ic|systemctl --user import-environment}} を使う。環境変数を設定した後に起動したユーザーユニットには影響しますが、既に起動しているユニットには影響しません。
 
:: {{Tip|1=複数の変数を一度に設定するには、空白で区切った ''key=value'' ペアのリストを設定ファイルに書き込んで、{{ic|xargs systemctl --user set-environment < /path/to/file.conf}} をシェルのスタートアップファイルに追加してください。}}
 
   
  +
{{Warning|systemd のサービスはセッションではありません。サービスは ''logind'' の外で動作します。linger を利用して自動ログインを有効にすると[[一般的なトラブルシューティング#セッションのパーミッション|セッションが破壊]]されるので注意してください。}}
設定するべき変数としては {{ic|DISPLAY}} や {{ic|PATH}} などが考えられます。
 
   
  +
== ユーザーユニットを書く ==
==== DISPLAY ====
 
   
  +
普通の systemd ユニットファイルの書き方は [[systemd#ユニットファイル]]を見てください。
{{Note|1=systemd 219 から、セッションが開始したときに {{ic|$DISPLAY}} と {{ic|$XAUTHORITY}} を {{ic|systemd --user}} デーモンの環境にアップロードする X11 セッションアプレットが付属するようになりました。これによって systemd ユーザーサービスで X11 のアプリケーションを実行するときの互換性が向上しています ([http://cgit.freedesktop.org/systemd/systemd/tree/NEWS?id=v219#n194 ソース])。}}
 
   
  +
=== サンプル ===
DISPLAY は X アプリケーションがどのディスプレイを使えばいいのか知るために使用されます。systemd ユニットから X アプリケーションを起動するつもりならば、この変数を設定しなくてはなりません。例:
 
  +
以下は mpd サービスのユーザーバージョンの例です。
  +
{{hc|~/.config/systemd/user/mpd.service|<nowiki>
  +
[Unit]
  +
Description=Music Player Daemon
   
  +
[Service]
{{hc|/etc/systemd/user.conf|<nowiki>
 
  +
ExecStart=/usr/bin/mpd --no-daemon
...
 
  +
DefaultEnvironment=DISPLAY=:0
 
  +
[Install]
...
 
  +
WantedBy=default.target
 
</nowiki>}}
 
</nowiki>}}
   
  +
=== 変数を使用したサンプル ===
もしくは xinitrc スクリプトをインストールして適切な環境変数を取得することもできます:
 
   
  +
以下は {{ic|sickbeard.service}} のユーザーバージョンの例で、[[SickBeard]] が特定のファイルを見つけられるようホームディレクトリの変数を使っています:
{{hc|/etc/X11/xinit/xinitrc.d/import-display.sh|<nowiki>
 
  +
{{hc|~/.config/systemd/user/sickbeard.service|<nowiki>
#!/bin/sh
 
  +
[Unit]
  +
Description=SickBeard Daemon
   
  +
[Service]
systemctl --user import-environment DISPLAY XAUTHORITY
 
  +
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard
  +
  +
[Install]
  +
WantedBy=default.target
 
</nowiki>}}
 
</nowiki>}}
   
  +
{{ic|man systemd.unit}} に書かれているように、{{ic|%h}} 変数はサービスを実行しているユーザーのホームディレクトリに置き換えられます。他にも [[systemd]] のマニュアルページで示されている変数が存在します。
==== PATH ====
 
   
  +
=== X アプリケーションについての注意 ===
{{ic|PATH}} 変数を {{ic|.bashrc}} や {{ic|.bash_profile}} で設定しても systemd では使うことができません。{{ic|PATH}} をカスタマイズしており、それを利用するアプリケーションを systemd ユニットから起動する予定があるなら、systemd 環境に {{ic|PATH}} を設定する必要があります。{{ic|PATH}} を {{ic|.bash_profile}} に設定している場合、以下を {{ic|PATH}} 変数を設定した後の {{ic|.bash_profile}} に追加するのが systemd で {{ic|PATH}} を設定する一番簡単な方法です:
 
   
  +
ほとんどの X アプリは実行するのに {{ic|DISPLAY}} 変数を必要とします。systemd のユーザーインスタンスでこの変数を設定する方法は [[#DISPLAY と XAUTHORITY]] を見て下さい。
{{hc|~/.bash_profile|<nowiki>
 
systemctl --user import-environment PATH
 
</nowiki>}}
 
   
=== systemd のユザーインスタンス自動起動 ===
+
=== ジャナル読み込む ===
   
  +
ユーザーのジャーナルも同じようなコマンドで読みことができます:
systemd のユーザーインスタンスはデフォルトでユーザーの最初のログイン時に実行され、ユーザーのセッションが閉じられた時に終了します。しかしながら、ブートした直後にインスタンスを起動して、セッションが閉じられてもユーザーインスタンスを実行し続ける方が、例えばセッションが開いてない時もユーザープロセスを実行したいときなどには便利です。linger を利用してこれを行います。特定のユーザーで linger を有効にするには以下のコマンドを使用:
 
   
  +
$ journalctl --user
# loginctl enable-linger ''username''
 
   
  +
ユニットを指定する場合:
{{Warning|systemd のサービスはセッションではありません。サービスは ''logind'' の外で動作します。linger を利用して自動ログインを有効にすると[[一般的なトラブルシューティング#セッションのパーミッション|セッションが破壊]]されるので注意してください。}}
 
  +
  +
$ journalctl --user -u myunit.service
  +
  +
ユーザーユニットを指定する場合:
  +
  +
$ journalctl --user --user-unit myunit.service
  +
  +
ときどきユーザーサービスからの出力がサービスユニットに割り当てられないというバグが存在します。{{ic|-u}} を使って出力をフィルタリングするとサービスユニットからの出力が見れなくなる可能性があります。
  +
  +
== 一時ファイル ==
  +
  +
''systemd-tmpfiles'' を使うことでシステム全体と同じように一時ファイル・ディレクトリを管理することができます ([[systemd#一時ファイル]]を参照)。ユーザー個別の設定ファイルは {{ic|~/.config/user-tmpfiles.d/}} と {{ic|~/.local/share/user-tmpfiles.d/}} からこの順番で読み込まれます。設定ファイルを使うには、必要な systemd ユーザーユニットを使用しているユーザーで有効にする必要があります:
  +
  +
$ systemctl --user enable systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer
  +
  +
設定ファイルの構文はシステムユニットと同じです。詳しくは man ページの {{man|8|systemd-tmpfiles}} や {{man|5|tmpfiles.d}} を見てください。
   
 
== Xorg と systemd ==
 
== Xorg と systemd ==
161行目: 193行目:
   
 
バージョン 1.16 から {{Pkg|xorg-server}} は systemd とのより良い統合を2つの手段で提供しています:
 
バージョン 1.16 から {{Pkg|xorg-server}} は systemd とのより良い統合を2つの手段で提供しています:
* デバイス管理を logind に委託することで、非特権でも実行することが可能に ([http://cgit.freedesktop.org/xorg/xserver/commit/?id=82863656ec449644cd34a86388ba40f36cea11e9 このコミット] など Hans de Goede のコミットを参照)。
+
* デバイス管理を logind に委託することで、非特権でも実行することが可能に ([https://cgit.freedesktop.org/xorg/xserver/commit/?id=82863656ec449644cd34a86388ba40f36cea11e9 このコミット] など Hans de Goede のコミットを参照)。
* ソケットによってサービスを有効化することが可能に ([http://cgit.freedesktop.org/xorg/xserver/commit/?id=b3d3ffd19937827bcbdb833a628f9b1814a6e189 このコミット] を参照)。これによって {{AUR|systemd-xorg-launch-helper-git}} が不要に。
+
* ソケットによってサービスを有効化することが可能に ([https://cgit.freedesktop.org/xorg/xserver/commit/?id=b3d3ffd19937827bcbdb833a628f9b1814a6e189 このコミット] を参照)。これによって {{AUR|systemd-xorg-launch-helper-git}} が不要に。
   
 
残念ながら、非特権モードで xorg を実行できるようにするには、セッションの中で xorg を実行する必要があります。そのため、今のところユーザーサービスとして xorg を実行するのには (1.16 以前と同じように) root 権限で実行する必要があるというハンディキャップがあり、1.16 で導入された非特権モードを活用することはできません。
 
残念ながら、非特権モードで xorg を実行できるようにするには、セッションの中で xorg を実行する必要があります。そのため、今のところユーザーサービスとして xorg を実行するのには (1.16 以前と同じように) root 権限で実行する必要があるというハンディキャップがあり、1.16 で導入された非特権モードを活用することはできません。
   
{{Note|This is not a fundamental restriction imposed by logind, but the reason seems to be that xorg needs to know which session to take over, and right now it gets this information calling [http://www.freedesktop.org/wiki/Software/systemd/logind logind]'s {{ic|GetSessionByPID}} using its own pid as argument. See [http://lists.x.org/archives/xorg-devel/2014-February/040476.html this thread] and [http://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/os-support/linux/systemd-logind.c xorg sources]. It seems likely that xorg could be modified to get the session from the tty it is attaching to, and then it could run unprivileged from a user service outside a session.}}
+
{{Note|上記の制約は logind によるものではなく、xorg にどのセッションを引き継ぐか知らせる必要があるのが理由です。現在の実装では自己の pid を引数として [https://www.freedesktop.org/wiki/Software/systemd/logind logind] {{ic|GetSessionByPID}} を呼び出すことで情報を取得しています。[http://lists.x.org/archives/xorg-devel/2014-February/040476.html このスレッド] [https://cgit.freedesktop.org/xorg/xserver/tree/hw/xfree86/os-support/linux/systemd-logind.c xorg のソース] を参照してください。アタッチする tty からセッションを取得するように xorg を修正すれば、セッションの外でもユーザーサービスから非特権で実行することができます。}}
  +
  +
{{Warning|1=xorg 1.18 ではソケットアクティベーションが壊れているようです。クライアントからアクティベーションが実行されるとデッドロックが発生します。上流のバグレポート [https://bugs.freedesktop.org/show_bug.cgi?id=93072] を参照してください。回避策としては、ソケットアクティベーションを使わないで xorg サーバーを起動することで、サーバーが完全に起動するまでクライアントの接続を待機させることができます。X サーバーの起動を通知する機構は存在しません。}}
   
 
以下がユーザーサービスから xorg を起動する方法です:
 
以下がユーザーサービスから xorg を起動する方法です:
201行目: 235行目:
 
</nowiki>}}
 
</nowiki>}}
   
{{ic|${XDG_VTNR} }} は xorg が起動する仮想ミナルで、サービスユニットでハードコードするか、以下のコマンドを使って systemd 環境で設定します:
+
{{ic|${XDG_VTNR} }} は xorg が起動する仮想コンソールで、サービスユニットでハードコードするか、以下のコマンドを使って systemd 環境で設定します:
   
 
$ systemctl --user set-environment XDG_VTNR=1
 
$ systemctl --user set-environment XDG_VTNR=1
   
{{Note|xorg はユーザーがログインしたのと同じ仮想ミナルで起動する必要があります。そうでないと logind はセッションがアクティブになっていないと認識します。}}
+
{{Note|xorg はユーザーがログインしたのと同じ仮想コンソールで起動する必要があります。そうでないと logind はセッションがアクティブになっていないと認識します。}}
   
3. [[#DISPLAY|上]]で説明されているように {{ic|DISPLAY}} 環境変数を設定します。
+
3. [[#DISPLAY と XAUTHORITY|上]]で説明されているように {{ic|DISPLAY}} 環境変数を設定します。
   
 
4. 次に、display 0 と tty 2 で xorg のソケットアクティベーションを有効化します:
 
4. 次に、display 0 と tty 2 で xorg のソケットアクティベーションを有効化します:
214行目: 248行目:
 
$ systemctl --user start xorg@0.socket # Start listening on the socket for display 0
 
$ systemctl --user start xorg@0.socket # Start listening on the socket for display 0
   
これで X アプリケーションを実行すると仮想ミナル2で自動的に xorg が起動します。
+
これで X アプリケーションを実行すると仮想コンソール 2 で自動的に xorg が起動します。
   
 
{{ic|XDG_VTNR}} 環境変数は {{ic|.bash_profile}} から systemd 環境に設定することができ、ウィンドウマネージャなど、あらゆる X アプリケーションを {{ic|xorg@0.socket}} に依存する systemd ユニットとして起動することが可能です。
 
{{ic|XDG_VTNR}} 環境変数は {{ic|.bash_profile}} から systemd 環境に設定することができ、ウィンドウマネージャなど、あらゆる X アプリケーションを {{ic|xorg@0.socket}} に依存する systemd ユニットとして起動することが可能です。
   
{{Warning|現在、ユーザーサービスとしてウィンドウマネージャを実行するとセッションの外でウィンドウマネージャが実行されることになり次の問題が引き起こされます: [[一般的なトラブルシューティング#セッションのパーミッション|セッションの破壊]]。ただし、systemd の開発者はウィンドウマネージャの実行を可能にする何かを作る予定があるようです。[https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] や [http://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html] を見て下さい。}}
+
{{Warning|現在、ユーザーサービスとしてウィンドウマネージャを実行するとセッションの外でウィンドウマネージャが実行されることになり次の問題が引き起こされます: [[一般的なトラブルシューティング#セッションのパーミッション|セッションの破壊]]。ただし、systemd の開発者はウィンドウマネージャの実行を可能にする何かを作る予定があるようです。[https://mail.gnome.org/archives/desktop-devel-list/2014-January/msg00079.html] や [https://lists.freedesktop.org/archives/systemd-devel/2014-March/017552.html] を見て下さい。}}
 
== ユーザーユニットを書く ==
 
=== サンプル ===
 
以下は mpd サービスのユーザーバージョンの例です。
 
{{hc|~/.config/systemd/user/mpd.service|<nowiki>
 
[Unit]
 
Description=Music Player Daemon
 
 
[Service]
 
ExecStart=/usr/bin/mpd --no-daemon
 
 
[Install]
 
WantedBy=default.target
 
</nowiki>}}
 
=== 変数を使用したサンプル ===
 
以下は {{ic|sickbeard.service}} のユーザーバージョンの例で、SickBeard が特定のファイルを見つけられるようホームディレクトリの変数を使っています:
 
{{hc|~/.config/systemd/user/sickbeard.service|<nowiki>
 
[Unit]
 
Description=SickBeard Daemon
 
 
[Service]
 
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard
 
 
[Install]
 
WantedBy=default.target
 
</nowiki>}}
 
 
{{ic|man systemd.unit}} に書かれているように、{{ic|%h}} 変数はサービスを実行しているユーザーのホームディレクトリに置き換えられます。他にも [[systemd]] のマニュアルページで示されている変数が存在します。
 
 
=== X アプリケーションについての注意 ===
 
 
ほとんどの X アプリは実行するのに {{ic|DISPLAY}} 変数を必要とします (あなたのサービスファイルが起動しない理由として第一に挙げられるでしょう)。systemd のユーザーインスタンスでこの変数を設定する方法は [[#DISPLAY]] を見て下さい。もしくは、以下のようにユニットでこの変数を設定することもできます:
 
 
{{hc|~/.config/systemd/user/parcellite.service|2=
 
[Unit]
 
Description=Parcellite clipboard manager
 
 
[Service]
 
ExecStart=/usr/bin/parcellite
 
'''Environment=DISPLAY=:0'''
 
 
[Install]
 
WantedBy=mystuff.target
 
}}
 
   
 
== ユースケース ==
 
== ユースケース ==
283行目: 273行目:
 
}}
 
}}
   
  +
上記の {{ic|mystuff.target}} と同じように、{{ic|cruft.target}} は tmux や screen が起動する前に実行する必要があるサービス (もしくは起動時に即座に起動させたいサービス)、例えば GnuPG デーモンのセッションなどを起動します。
{{ic|cruft.target}}, like {{ic|mystuff.target}} above, should start anything you think should run before tmux or screen starts (or which you want started at boot regardless of timing), such as a GnuPG daemon session.
 
   
  +
次にマルチプレクサセッションのサービスを作成してください。以下は tmux を使用して {{ic|/tmp/gpg-agent-info}} に情報を書き込む gpg-agent セッションを読み込むサービスの例です。また、DISPLAY を設定することで X を起動したときに X プログラムが実行できるようにしています。
You then need to create a service for your multiplexer session. Here is a sample service, using tmux as an example and sourcing a gpg-agent session which wrote its information to {{ic|/tmp/gpg-agent-info}}. This sample session, when you start X, will also be able to run X programs, since DISPLAY is set.
 
   
 
{{bc|1=
 
{{bc|1=
305行目: 295行目:
 
}}
 
}}
   
Once this is done, {{ic|systemctl --user enable}} {{ic|tmux.service}}, {{ic|multiplexer.target}} and any services you created to be run by {{ic|cruft.target}} and you should be set to go! Activated {{ic|user-session@.service}} as described above, but be sure to remove the {{ic|1=Conflicts=getty@tty1.service}} from {{ic|user-session@.service}}, since your user session will not be taking over a TTY. Congratulations! You have a running terminal multiplexer and some other useful programs ready to start at boot!
+
上記の設定が完了したら、{{ic|systemctl --user enable}} {{ic|tmux.service}}, {{ic|multiplexer.target}} {{ic|cruft.target}} で実行させるサービスを有効化してください。後は同じように {{ic|user-session@.service}} を有効化しますが、ユーザーセッションは TTY を引き継がないので {{ic|user-session@.service}} から {{ic|1=Conflicts=getty@tty1.service}} は削除してください。これで、起動時にターミナルマルチプレクサなどのプログラムを実行できるようになります。
   
 
=== ウィンドウマネージャ ===
 
=== ウィンドウマネージャ ===
326行目: 316行目:
 
</nowiki>}}
 
</nowiki>}}
   
{{Note|The {{ic|[Install]}} section includes a {{ic|WantedBy}} part. When using {{ic|systemctl --user enable}} it will link this as {{ic|~/.config/systemd/user/wm.target.wants/''window_manager''.service}}, allowing it to be started at login. Is recommended to enable this service, not to link it manually.}}
+
{{Note|{{ic|[Install]}} セクションに {{ic|WantedBy}} を記述することで、{{ic|systemctl --user enable}} を使用した際に {{ic|~/.config/systemd/user/wm.target.wants/''window_manager''.service}} としてリンクが作成され、ログイン時に起動できるようになります。リンクは手動で作成するのではなく、サービスを有効化することを推奨します。}}
  +
  +
== ログアウト時にユーザープロセスを終了 ==
  +
  +
{{pkg|systemd}} パッケージのデフォルトは {{ic|1=KillUserProcesses=no}} となっており、ユーザーが完全にログアウトしたときでもユーザープロセスは終了しません。ユーザーがログアウトしたときに全てのユーザープロセスが終了するようにしたい場合、{{ic|/etc/systemd/logind.conf}} に {{ic|1=KillUserProcesses=yes}} と設定してください。
  +
  +
ただし、この設定を変更すると [[tmux]] や [[screen]] などのターミナルマルチプレクサが動作しなくなります。以下のように {{ic|systemd-run}} を使ってターミナルマルチプレクサを利用してください:
  +
  +
$ systemd-run --scope --user ''command'' ''args''
  +
  +
例えば、{{ic|screen}} を実行する場合:
  +
  +
$ systemd-run --scope --user screen -S ''foo''
  +
  +
{{ic|systemd-run}} を使うと、ログアウト後も、ユーザがシステム内のどこかで少なくとも 1 回はログインしていて、{{ic|user@.service}} がまだ実行されている間だけ、プロセスが実行され続けます。
  +
  +
ユーザがすべてのセッションからログアウトした後、{{ic|user@.service}} は、そのユーザが「lingering」を有効にしていない限り、デフォルトで終了します [https://github.com/systemd/systemd/blob/76153ad45f09b6ae45464f2e03d3afefbb4b2afe/NEWS#L274]。ユーザーが完全にログアウトしていても、長時間のタスクを効果的に実行できるようにするには、そのユーザーに対してリンガリングを有効にする必要があります。詳しくは [[#Automatic start-up of systemd user instances]] と {{man|1|loginctl}} を参照してください。
  +
  +
== トラブルシューティング ==
  +
  +
=== ランタイムディレクトリ '/run/user/1000' は、UID1000 によって所有されていません ===
  +
  +
systemd[1867]: pam_systemd(systemd-user:session): Runtime directory '/run/user/1000' is not owned by UID 1000, as it should.
  +
systemd[1867]: Trying to run as user instance, but $XDG_RUNTIME_DIR is not set
  +
  +
このようなエラーが表示され、ログインセッションが壊れている場合、システム上の別のシステム(ユーザーではない)サービスがこのフォルダを作成している可能性があります。例えば、{{ic|/run/user/1000}} にバインドマウントしている [[docker]] コンテナを使用している場合、このようなことが起こる可能性があります。これを解決するには、マウントを削除することでコンテナを修正するか、ドッカーサービスを無効化/遅延させるかのいずれかです。
   
 
== 参照 ==
 
== 参照 ==
 
* [https://bitbucket.org/KaiSforza/systemd-user-units/wiki/Home KaiSforza's bitbucket wiki]
 
* [https://bitbucket.org/KaiSforza/systemd-user-units/wiki/Home KaiSforza's bitbucket wiki]
 
* [https://github.com/zoqaeski/systemd-user-units Zoqaeski's units on Github]
 
* [https://github.com/zoqaeski/systemd-user-units Zoqaeski's units on Github]
* [https://github.com/grawity/systemd-user-units Collection of useful systemd user units]
 
 
* [https://bbs.archlinux.org/viewtopic.php?id=167115 Forum thread about changes in systemd 206 user instances]
 
* [https://bbs.archlinux.org/viewtopic.php?id=167115 Forum thread about changes in systemd 206 user instances]

2023年7月3日 (月) 14:30時点における最新版

関連記事

systemd はユーザーに systemd のインスタンスを実行させてサービスを管理できる機能を提供しています。これによって systemd がユーザーによって実行されている時、特定のディレクトリに入っているユニットをユーザーが起動・停止・有効化・無効化することが可能です。このことは root や特別なユーザーではなく普通のユーザーとして通常実行される mpd などのデーモン・サービスで重宝します。また、メールの取得などの作業を自動化することも可能です。さらに、多少の注意が必要ですが、ユーザーサービスから xorg やウィンドウマネージャを実行することもできます。

利用方法

ユーザーがログインを行うと、systemd は自動的にユーザーサービスを管理する systemd --user インスタンスを起動します。このプロセスは、そのユーザーにセッションが残っているかぎり生存し、ユーザーの最後のセッションが閉じられた時に終了します。systemd のユーザーインスタンスを自動起動している場合、インスタンスはブート時に起動し、終了しません。ユーザーサービスを使うことで、ソケットアクティベーションやタイマー、システムの依存関係や cgroups によるプロセスの制限など、systemd の恩恵を最大限活用して、デーモンや自動化されたタスクを実行できます。

ユーザーユニットはシステムサービスと同じように以下のディレクトリに配置されます (優先度が低い順):

  • /usr/lib/systemd/user/: インストールしたパッケージに含まれているサービス
  • ~/.local/share/systemd/user/: ホームディレクトリにインストールしたパッケージのユニット
  • /etc/systemd/user/: システムの管理者が配置する、全てのユーザーが使えるユーザーサービス
  • ~/.config/systemd/user/: ユーザーが配置する、そのユーザーのサービス

systemd のユーザーインスタンスが起動すると、default.target ターゲットが立ち上がります。その後 systemctl --user を使って手動で systemd のユーザーインスタンスを制御できるようになります。

ノート:
  • バージョン206から、systemd --user インスタンスはユーザーごとのプロセスであり、セッションごとのプロセスではないので注意してください。ソケットやステートファイルなどのユーザーサービスによって扱われるリソースはセッションごとではなくユーザーごとに割り振られる (ユーザーのホームディレクトリ上に存在する) というのが原則です。つまりユーザーサービスは全てセッションとは関係なく動作します。結果として、セッションの中で実行する必要があるプログラムはユーザーサービスの中で壊れてしまう可能性があります。systemd のユーザーセッションの扱い方は流動的であり確定していません。[1][2] が今後どうなるかのヒントになるでしょう。
  • systemd --usersystemd --system プロセスとは別のプロセスを起動します。ユーザーユニットからシステムユニットに依存したり参照することはできません。

基本設定

Systemd のユーザーインスタンスはログイン時に自動で起動します。正しく起動していることを確認するには、次のコマンドを使います: systemctl --user status

ユーザーサービスは全て ~/.config/systemd/user/ に配置してください。ログイン時にサービスを実行したい場合は、自動実行したいサービスごとに systemctl --user enable service を実行してください。

D-Bus

プログラムによっては D-Bus ユーザーメッセージバスを必要とすることがあります。D-Bus は伝統的に dbus-launch によってデスクトップ環境の起動時に実行されていましたが、バージョン226から、systemd がユーザーのメッセージバスを管理するようになりました [3]dbus.socketdbus.service のユーザーユニットによって全てのセッションでユーザーごとに dbus-daemon が起動します。

ノート: /etc/systemd/user/~/.config/systemd/user/ に手動でユニットを作成していた場合は、削除してもかまいません。

環境変数

systemd のユーザーインスタンスは .bashrc などに設定された環境変数を全く継承しません。systemd インスタンスに環境変数を設定する方法は複数存在します:

  1. $HOME ディレクトリが存在するユーザーの場合、~/.config/environment.d/ ディレクトリに NAME=VAL という形式で環境変数を記述した .conf ファイルを作成する。ユーザーのユニットファイルにのみ影響します。詳しくは environment.d(5) を見てください。
  2. /etc/systemd/user.confDefaultEnvironment オプションを使う。全てのユーザーユニットに影響します。
  3. /etc/systemd/system/user@.service.d/ に設定ファイルを追加する。全てのユーザーユニットに影響します。#サービス例を参照。
  4. 適宜、systemctl --user set-environmentsystemctl --user import-environment を使う。環境変数を設定した後に起動したユーザーユニットには影響しますが、既に起動しているユニットには影響しません。
  5. D-Busdbus-update-activation-environment --systemd --all コマンドを使う。systemctl --user import-environment と同じ効果があり、D-Bus セッションに適用されます。コマンドはシェルの初期化ファイルの末尾に追加できます。
  6. ユーザー環境全体の環境変数は systemd のジェネレータによって読み込まれる environment.d ディレクトリを使用できます。詳しくは environment.d(5) を参照。
  7. 環境生成スクリプトを記述することでユーザーごとに環境変数を生成することもできます。ユーザーごとに環境変数を設定する必要は役に立つでしょう (XDG_RUNTIME_DIR, DBUS_SESSION_BUS_ADDRESS など)。systemd.environment-generator(7) を見てください。

設定するべき変数としては DISPLAYPATH などが考えられます。

サービス例

ドロップインディレクトリ /etc/systemd/system/user@.service.d/ を作成して、その中に拡張子が .conf のファイルを作成します (例: local.conf):

/etc/systemd/system/user@.service.d/local.conf
[Service]
Environment="PATH=/usr/lib/ccache/bin:/usr/local/bin:/usr/bin:/bin"
Environment="EDITOR=nano -c"
Environment="BROWSER=firefox"
Environment="NO_AT_BRIDGE=1"

DISPLAY と XAUTHORITY

DISPLAY は X アプリケーションがどのディスプレイを使えばいいのか知るために使用されます。XAUTHORITY はユーザーの .Xauthority ファイルのパスと、X サーバーにアクセスするのに必要な cookie を指定します。systemd ユニットから X アプリケーションを起動する場合、これらの変数を設定する必要があります。バージョン 219 から、セッションが開始したときに DISPLAYXAUTHORITYsystemd --user デーモンの環境にアップロードする X11 セッションアプレット /etc/X11/xinit/xinitrc.d/50-systemd-user.sh が systemd に付属するようになりました。これによって、X を標準の方法で起動しているかぎり、ユーザーサービスは DISPLAYXAUTHORITY を使用することができるようになっています。

PATH

PATH 変数を .bashrc.bash_profile で設定しても systemd では使うことができません。PATH をカスタマイズしており、それを利用するアプリケーションを systemd ユニットから起動する予定があるなら、systemd 環境に PATH を設定する必要があります。PATH.bash_profile に設定している場合、以下を PATH 変数を設定した後の .bash_profile に追加するのが systemd で PATH を設定する一番簡単な方法です:

~/.bash_profile
systemctl --user import-environment PATH

pam_environment

pam_env.so モジュールを利用することで環境変数を設定できます。~/.pam_environment ファイルを以下のように作成してください:

~/.pam_environment
XDG_CONFIG_HOME DEFAULT=@{HOME}/.local/config
XDG_DATA_HOME   DEFAULT=@{HOME}/.local/data

.pam_environment ファイルの構文に関する詳細は環境変数#pam_env を使うを見てください。systemctl --user show-environment コマンドを実行することで設定が上手くいっているか確認できます:

$ systemctl --user show-environment
...
XDG_CONFIG_HOME=/home/user/.local/config
XDG_DATA_HOME=/home/user/.local/data
...

systemd のユーザーインスタンスを自動起動

systemd のユーザーインスタンスはデフォルトでユーザーの最初のログイン時に実行され、ユーザーのセッションが閉じられた時に終了します。しかしながら、ブートした直後にインスタンスを起動して、セッションが閉じられてもユーザーインスタンスを実行し続ける方が、例えばセッションが開いてない時もユーザープロセスを実行したいときなどには便利です。linger を利用してこれを行います。特定のユーザーで linger を有効にするには以下のコマンドを使用:

# loginctl enable-linger username
警告: systemd のサービスはセッションではありません。サービスは logind の外で動作します。linger を利用して自動ログインを有効にするとセッションが破壊されるので注意してください。

ユーザーユニットを書く

普通の systemd ユニットファイルの書き方は systemd#ユニットファイルを見てください。

サンプル

以下は mpd サービスのユーザーバージョンの例です。

~/.config/systemd/user/mpd.service
[Unit]
Description=Music Player Daemon

[Service]
ExecStart=/usr/bin/mpd --no-daemon

[Install]
WantedBy=default.target

変数を使用したサンプル

以下は sickbeard.service のユーザーバージョンの例で、SickBeard が特定のファイルを見つけられるようホームディレクトリの変数を使っています:

~/.config/systemd/user/sickbeard.service
[Unit]
Description=SickBeard Daemon

[Service]
ExecStart=/usr/bin/env python2 /opt/sickbeard/SickBeard.py --config %h/.sickbeard/config.ini --datadir %h/.sickbeard

[Install]
WantedBy=default.target

man systemd.unit に書かれているように、%h 変数はサービスを実行しているユーザーのホームディレクトリに置き換えられます。他にも systemd のマニュアルページで示されている変数が存在します。

X アプリケーションについての注意

ほとんどの X アプリは実行するのに DISPLAY 変数を必要とします。systemd のユーザーインスタンスでこの変数を設定する方法は #DISPLAY と XAUTHORITY を見て下さい。

ジャーナルを読み込む

ユーザーのジャーナルも同じようなコマンドで読みことができます:

$ journalctl --user

ユニットを指定する場合:

$ journalctl --user -u myunit.service

ユーザーユニットを指定する場合:

$ journalctl --user --user-unit myunit.service

ときどきユーザーサービスからの出力がサービスユニットに割り当てられないというバグが存在します。-u を使って出力をフィルタリングするとサービスユニットからの出力が見れなくなる可能性があります。

一時ファイル

systemd-tmpfiles を使うことでシステム全体と同じように一時ファイル・ディレクトリを管理することができます (systemd#一時ファイルを参照)。ユーザー個別の設定ファイルは ~/.config/user-tmpfiles.d/~/.local/share/user-tmpfiles.d/ からこの順番で読み込まれます。設定ファイルを使うには、必要な systemd ユーザーユニットを使用しているユーザーで有効にする必要があります:

$ systemctl --user enable systemd-tmpfiles-setup.service systemd-tmpfiles-clean.timer

設定ファイルの構文はシステムユニットと同じです。詳しくは man ページの systemd-tmpfiles(8)tmpfiles.d(5) を見てください。

Xorg と systemd

systemd ユニットの中で Xorg を実行する方法は複数存在します。以下の2つは、xorg プロセスで新しいユーザーセッションを起動するというのと、systemd のユーザーサービスから xorg を起動するという方法です。

ディスプレイマネージャを使わずに Xorg に自動ログイン

こちらを選択した場合、xorg サーバーでユーザーセッションを起動してその後ウィンドウマネージャなどを起動するために通常の ~/.xinitrc を実行するシステムユニットを起動します。

D-Bus を適切に設定して xlogin-gitAUR をインストールする必要があります。

雛形のファイルから xinitrc を設定して、/etc/X11/xinit/xinitrc.d/ のファイルが読み込まれるようにしてください。~/.xinitrc は実行したときに戻ってこないようにする必要があるため、最後のコマンドとして wait を記述するか、(ウィンドウマネージャなど) exec を追加して戻ってこないようにしてください。

セッションは自らの dbus デーモンを使用しますが、systemd ユーティリティは dbus.service インスタンスに自動的に接続します。

最後に、(root で) xlogin を有効にして起動時に自動ログインするようにしてください:

# systemctl enable xlogin@username

ユーザーセッションが systemd の範囲の中に収まるようになってユーザーセッションの全てが問題なく動作するはずです。

systemd のユーザーサービスとしての Xorg

また、systemd のユーザーサービスの中から Xorg を実行することもできます。他の X 関連のユニットを Xorg などに依存させることができるという点では有利な一方、以下で説明するようにいくつか欠点が存在します。

バージョン 1.16 から xorg-server は systemd とのより良い統合を2つの手段で提供しています:

  • デバイス管理を logind に委託することで、非特権でも実行することが可能に (このコミット など Hans de Goede のコミットを参照)。
  • ソケットによってサービスを有効化することが可能に (このコミット を参照)。これによって systemd-xorg-launch-helper-gitAUR が不要に。

残念ながら、非特権モードで xorg を実行できるようにするには、セッションの中で xorg を実行する必要があります。そのため、今のところユーザーサービスとして xorg を実行するのには (1.16 以前と同じように) root 権限で実行する必要があるというハンディキャップがあり、1.16 で導入された非特権モードを活用することはできません。

ノート: 上記の制約は logind によるものではなく、xorg にどのセッションを引き継ぐか知らせる必要があるのが理由です。現在の実装では自己の pid を引数として logindGetSessionByPID を呼び出すことで情報を取得しています。このスレッドxorg のソース を参照してください。アタッチする tty からセッションを取得するように xorg を修正すれば、セッションの外でもユーザーサービスから非特権で実行することができます。
警告: xorg 1.18 ではソケットアクティベーションが壊れているようです。クライアントからアクティベーションが実行されるとデッドロックが発生します。上流のバグレポート [4] を参照してください。回避策としては、ソケットアクティベーションを使わないで xorg サーバーを起動することで、サーバーが完全に起動するまでクライアントの接続を待機させることができます。X サーバーの起動を通知する機構は存在しません。

以下がユーザーサービスから xorg を起動する方法です:

1. /etc/X11/Xwrapper.config を編集して、xorg が root 権限を使ってどのユーザーでも動作するようにします:

/etc/X11/Xwrapper.config
allowed_users=anybody
needs_root_rights=yes

2. 以下のユニットを ~/.config/systemd/user に追加:

~/.config/systemd/user/xorg@.socket
[Unit]
Description=Socket for xorg at display %i

[Socket]
ListenStream=/tmp/.X11-unix/X%i
~/.config/systemd/user/xorg@.service
[Unit]
Description=Xorg server at display %i

Requires=xorg@%i.socket
After=xorg@%i.socket

[Service]
Type=simple
SuccessExitStatus=0 1

ExecStart=/usr/bin/Xorg :%i -nolisten tcp -noreset -verbose 2 "vt${XDG_VTNR}"

${XDG_VTNR} は xorg が起動する仮想コンソールで、サービスユニットでハードコードするか、以下のコマンドを使って systemd 環境で設定します:

$ systemctl --user set-environment XDG_VTNR=1
ノート: xorg はユーザーがログインしたのと同じ仮想コンソールで起動する必要があります。そうでないと logind はセッションがアクティブになっていないと認識します。

3. で説明されているように DISPLAY 環境変数を設定します。

4. 次に、display 0 と tty 2 で xorg のソケットアクティベーションを有効化します:

$ systemctl --user set-environment XDG_VTNR=2     # So that xorg@.service knows which vt use
$ systemctl --user start xorg@0.socket            # Start listening on the socket for display 0

これで X アプリケーションを実行すると仮想コンソール 2 で自動的に xorg が起動します。

XDG_VTNR 環境変数は .bash_profile から systemd 環境に設定することができ、ウィンドウマネージャなど、あらゆる X アプリケーションを xorg@0.socket に依存する systemd ユニットとして起動することが可能です。

警告: 現在、ユーザーサービスとしてウィンドウマネージャを実行するとセッションの外でウィンドウマネージャが実行されることになり次の問題が引き起こされます: セッションの破壊。ただし、systemd の開発者はウィンドウマネージャの実行を可能にする何かを作る予定があるようです。[5][6] を見て下さい。

ユースケース

永続的なターミナルマルチプレクサ

ウィンドウマネージャのセッションにログインする代わりに、ユーザーセッションでデフォルトで GNU ScreenTmux などのターミナルマルチプレクサをバックグラウンドで実行したいということもあるでしょう。X ログインとログインを分割するのはディスプレイマネージャの代わりに TTY で起動したい場合にのみ有用です (その場合すべてを myStuff.target で起動するように記述できます)。

上述のようなタイプのユーザーセッションを作成するには、wm.target を作成する代わりに、multiplexer.target を作成します:

[Unit]
Description=Terminal multiplexer
Documentation=info:screen man:screen(1) man:tmux(1)
After=cruft.target
Wants=cruft.target

[Install]
Alias=default.target

上記の mystuff.target と同じように、cruft.target は tmux や screen が起動する前に実行する必要があるサービス (もしくは起動時に即座に起動させたいサービス)、例えば GnuPG デーモンのセッションなどを起動します。

次にマルチプレクサセッションのサービスを作成してください。以下は tmux を使用して /tmp/gpg-agent-info に情報を書き込む gpg-agent セッションを読み込むサービスの例です。また、DISPLAY を設定することで X を起動したときに X プログラムが実行できるようにしています。

[Unit]
Description=tmux: A terminal multiplixer
Documentation=man:tmux(1)
After=gpg-agent.service
Wants=gpg-agent.service

[Service]
Type=forking
ExecStart=/usr/bin/tmux start
ExecStop=/usr/bin/tmux kill-server
Environment=DISPLAY=:0
EnvironmentFile=/tmp/gpg-agent-info

[Install]
WantedBy=multiplexer.target

上記の設定が完了したら、systemctl --user enabletmux.service, multiplexer.targetcruft.target で実行させるサービスを有効化してください。後は同じように user-session@.service を有効化しますが、ユーザーセッションは TTY を引き継がないので user-session@.service から Conflicts=getty@tty1.service は削除してください。これで、起動時にターミナルマルチプレクサなどのプログラムを実行できるようになります。

ウィンドウマネージャ

systemd のサービスとしてウィンドウマネージャを実行するには、まず Xorg を systemd のユーザーサービスとして実行する必要があります。以下では awesome を例として使います:

~/.config/systemd/user/awesome.service
[Unit]
Description=Awesome window manager
After=xorg.target
Requires=xorg.target

[Service]
ExecStart=/usr/bin/awesome
Restart=always
RestartSec=10
 
[Install]
WantedBy=wm.target
ノート: [Install] セクションに WantedBy を記述することで、systemctl --user enable を使用した際に ~/.config/systemd/user/wm.target.wants/window_manager.service としてリンクが作成され、ログイン時に起動できるようになります。リンクは手動で作成するのではなく、サービスを有効化することを推奨します。

ログアウト時にユーザープロセスを終了

systemd パッケージのデフォルトは KillUserProcesses=no となっており、ユーザーが完全にログアウトしたときでもユーザープロセスは終了しません。ユーザーがログアウトしたときに全てのユーザープロセスが終了するようにしたい場合、/etc/systemd/logind.confKillUserProcesses=yes と設定してください。

ただし、この設定を変更すると tmuxscreen などのターミナルマルチプレクサが動作しなくなります。以下のように systemd-run を使ってターミナルマルチプレクサを利用してください:

$ systemd-run --scope --user command args

例えば、screen を実行する場合:

$ systemd-run --scope --user screen -S foo

systemd-run を使うと、ログアウト後も、ユーザがシステム内のどこかで少なくとも 1 回はログインしていて、user@.service がまだ実行されている間だけ、プロセスが実行され続けます。

ユーザがすべてのセッションからログアウトした後、user@.service は、そのユーザが「lingering」を有効にしていない限り、デフォルトで終了します [7]。ユーザーが完全にログアウトしていても、長時間のタスクを効果的に実行できるようにするには、そのユーザーに対してリンガリングを有効にする必要があります。詳しくは #Automatic start-up of systemd user instancesloginctl(1) を参照してください。

トラブルシューティング

ランタイムディレクトリ '/run/user/1000' は、UID1000 によって所有されていません

systemd[1867]: pam_systemd(systemd-user:session): Runtime directory '/run/user/1000' is not owned by UID 1000, as it should.
systemd[1867]: Trying to run as user instance, but $XDG_RUNTIME_DIR is not set

このようなエラーが表示され、ログインセッションが壊れている場合、システム上の別のシステム(ユーザーではない)サービスがこのフォルダを作成している可能性があります。例えば、/run/user/1000 にバインドマウントしている docker コンテナを使用している場合、このようなことが起こる可能性があります。これを解決するには、マウントを削除することでコンテナを修正するか、ドッカーサービスを無効化/遅延させるかのいずれかです。

参照