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

提供: ArchWiki
ナビゲーションに移動 検索に移動
(同期)
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] や [http://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'' ファイルが存在していないかチェックしてください。}}
 
 
ユーザーサービスは全て {{ic|~/.config/systemd/user}} に配置してください。ログイン時にサービスを実行したい場合は、自動実行したいサービスごとに {{ic|systemctl --user enable ''service''}} を実行してください。
 
 
{{Note|バージョン 206 から、systemd のユーザーインスタンスの仕組みは変更されています。現在、デフォルトで {{ic|pam_systemd.so}} モジュールがユーザーインスタンスを起動します。手動で起動する必要はありません。{{AUR|user-session-units}} の {{ic|user-session@.service}} は廃止されました。この変更によって {{ic|systemd --user}} はユーザーセッションの外で実行されます。}}
 
   
 
=== D-Bus ===
 
=== D-Bus ===
   
プログラムによっては [[D-Bus]] ユーザーメッセージバスを必要とすることがあります。D-Bus は伝統的に {{ic|dbus-launch}} によってデスクトップ環境の起動時に実行されています。かしながら、D-Bus に依存するプログラムを systemd ユーザーとして使う場合、依存関係解決するためD-Bus サーバーも systemd ビスとし実行する必要が出ます。
+
プログラムによっては [[D-Bus]] ユーザーメッセージバスを必要とすることがあります。D-Bus は伝統的に {{ic|dbus-launch}} によってデスクトップ環境の起動時に実行されていまし、バージョン206から、systemd ユーザーのメッセジバスを管理するようなりました [https://www.archlinuxjp.org/news/d-bus-now-launches-user-buses/]。{{ic|dbus.socket}} {{ic|dbus.service}} のユザーユニットによっのセッションでユーザーごとに ''dbus-daemon'' が起動します。
 
{{Note|将来 systemd から kdbus への移行がされることで、systemd はシステムとユーザーのメッセージバスのマネージャになります。}}
 
 
D-Bus を systemd サービスとして設定するには、以下を行う必要があります:
 
 
1. dbus サーバーのサービスユニットとソケットユニットを {{ic|/etc/systemd/user/}} に追加:
 
 
{{hc|/etc/systemd/user/dbus.socket|<nowiki>
 
[Unit]
 
Description=D-Bus User Message Bus Socket
 
 
[Socket]
 
ListenStream=%t/bus
 
 
[Install]
 
WantedBy=sockets.target
 
Also=dbus.service
 
</nowiki>}}
 
 
{{hc|/etc/systemd/user/dbus.service|<nowiki>
 
[Unit]
 
Description=D-Bus User Message Bus
 
Documentation=man:dbus-daemon(1)
 
Requires=dbus.socket
 
 
[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
 
 
[Install]
 
Also=dbus.socket
 
</nowiki>}}
 
 
2. 環境変数 {{ic|DBUS_SESSION_BUS_ADDRESS}} を設定。以下のファイルを作成して、{{ic|user@.service}} の設定ファイルを使うことで設定できます:
 
 
{{hc|/etc/systemd/system/user@.service.d/dbus.conf|<nowiki>
 
[Service]
 
Environment=DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%I/bus
 
</nowiki>}}
 
 
{{Note|systemd 209 以前は {{ic|DBUS_SESSION_BUS_ADDRESS}} は上流の {{ic|user@.service}} ユニットで設定されていました。現在は異なります。kdbus への移行が完了したら、{{ic|pam_systemd.so}} によって変数が設定されるようになるから、というのが理由のようです。}}
 
 
3. root で以下を実行してソケットを有効化:
 
   
  +
{{Note|{{ic|/etc/systemd/user/}} や {{ic|~/.config/systemd/user/}} に手動でユニットを作成していた場合は、削除してもかまいません。}}
# systemctl --global enable dbus.socket
 
   
 
=== 環境変数 ===
 
=== 環境変数 ===
   
systemd のユーザーインスタンスは {{ic|.bashrc}} などに設定された[[環境変数]]を全く継承しません。systemd インスタンスに環境変数を設定する方法は3つあります:
+
systemd のユーザーインスタンスは {{ic|.bashrc}} などに設定された[[環境変数]]を全く継承しません。systemd インスタンスに環境変数を設定する方法は複数存在します:
   
 
# {{ic|/etc/systemd/user.conf}} で {{ic|DefaultEnvironment}} オプションを使う。全てのユーザーユニットに影響します。
 
# {{ic|/etc/systemd/user.conf}} で {{ic|DefaultEnvironment}} オプションを使う。全てのユーザーユニットに影響します。
# {{ic|/etc/systemd/system/user@.service.d/}} に設定ファイルを追加する。全てのユーザーユニットに影響します。
+
# {{ic|/etc/systemd/system/user@.service.d/}} に設定ファイルを追加する。全てのユーザーユニットに影響します。[[#サービス例]]を参照
 
# 適宜、{{ic|systemctl --user set-environment}} や {{ic|systemctl --user import-environment}} を使う。環境変数を設定した後に起動したユーザーユニットには影響しますが、既に起動しているユニットには影響しません。
 
# 適宜、{{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 セッションに適用されます。コマンドはシェルの初期化ファイルの末尾に追加できます。
:: {{Tip|1=複数の変数を一度に設定するには、空白で区切った ''key=value'' ペアのリストを設定ファイルに書き込んで、{{ic|xargs systemctl --user set-environment < /path/to/file.conf}} をシェルのスタートアップファイルに追加してください。}}
 
   
 
設定するべき変数としては {{ic|DISPLAY}} や {{ic|PATH}} などが考えられます。
 
設定するべき変数としては {{ic|DISPLAY}} や {{ic|PATH}} などが考えられます。
   
==== DISPLAY ====
+
==== サービス例 ====
  +
[[Systemd#ドロップインスニペット|ドロップイン]]ディレクトリ {{ic|/etc/systemd/system/user@.service.d/}} を作成して、その中に拡張子が {{ic|.conf}} のファイルを作成します (例: {{ic|local.conf}}):
  +
{{hc|/etc/systemd/system/user@.service.d/local.conf|2=
  +
[Service]
  +
Environment="PATH=/usr/lib/ccache/bin/:$PATH"
  +
Environment="EDITOR=nano -c"
  +
Environment="BROWSER=firefox"
  +
Environment="NO_AT_BRIDGE=1"
  +
}}
   
  +
==== DISPLAY と XAUTHORITY ====
{{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 アプリケーションを起動するつもりならば、この変数を設定しなてはなせん例:
+
{{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}} を使用することができるようにってい
 
{{hc|/etc/systemd/user.conf|<nowiki>
 
...
 
DefaultEnvironment=DISPLAY=:0
 
...
 
</nowiki>}}
 
 
もしくは xinitrc スクリプトをインストールして適切な環境変数を取得することもできます:
 
 
{{hc|/etc/X11/xinit/xinitrc.d/import-display.sh|<nowiki>
 
#!/bin/sh
 
 
systemctl --user import-environment DISPLAY XAUTHORITY
 
</nowiki>}}
 
   
 
==== PATH ====
 
==== PATH ====
167行目: 117行目:
   
 
{{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|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.}}
  +
  +
{{Warning|1=xorg 1.18 ではソケットアクティベーションが壊れているようです。クライアントからアクティベーションが実行されるとデッドロックが発生します。上流のバグレポート [https://bugs.freedesktop.org/show_bug.cgi?id=93072] を参照してください。回避策としては、ソケットアクティベーションを使わないで xorg サーバーを起動することで、サーバーが完全に起動するまでクライアントの接続を待機させることができます。X サーバーの起動を通知する機構は存在しません。}}
   
 
以下がユーザーサービスから xorg を起動する方法です:
 
以下がユーザーサービスから xorg を起動する方法です:
207行目: 159行目:
 
{{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 のソケットアクティベーションを有効化します:
250行目: 202行目:
 
=== X アプリケーションについての注意 ===
 
=== X アプリケーションについての注意 ===
   
ほとんどの X アプリは実行するのに {{ic|DISPLAY}} 変数を必要とします (あなたのサービスファイルが起動しない理由として第一に挙げられるでしょう)。systemd のユーザーインスタンスでこの変数を設定する方法は [[#DISPLAY]] を見て下さい。もしくは、以下のようにユニットでこの変数を設定することもできます:
+
ほとんどの X アプリは実行するのに {{ic|DISPLAY}} 変数を必要とします。systemd のユーザーインスタンスでこの変数を設定する方法は [[#DISPLAY と XAUTHORITY]] を見て下さい。
 
{{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行目: 223行目:
 
}}
 
}}
   
  +
上記の {{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=
326行目: 266行目:
 
</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}} としてリンクが作成され、ログイン時に起動できるようになります。リンクは手動で作成するのではなく、サービスを有効化することを推奨します。}}
   
 
== 参照 ==
 
== 参照 ==
 
* [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]

2016年3月2日 (水) 17:50時点における版

関連記事

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 によってデスクトップ環境の起動時に実行されていましたが、バージョン206から、systemd がユーザーのメッセージバスを管理するようになりました [3]dbus.socketdbus.service のユーザーユニットによって全てのセッションでユーザーごとに dbus-daemon が起動します。

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

環境変数

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

  1. /etc/systemd/user.confDefaultEnvironment オプションを使う。全てのユーザーユニットに影響します。
  2. /etc/systemd/system/user@.service.d/ に設定ファイルを追加する。全てのユーザーユニットに影響します。#サービス例を参照。
  3. 適宜、systemctl --user set-environmentsystemctl --user import-environment を使う。環境変数を設定した後に起動したユーザーユニットには影響しますが、既に起動しているユニットには影響しません。
  4. D-Busdbus-update-activation-environment --systemd --all コマンドを使う。systemctl --user import-environment と同じ効果があり、D-Bus セッションに適用されます。コマンドはシェルの初期化ファイルの末尾に追加できます。

設定するべき変数としては 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/:$PATH"
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

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

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

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

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 で導入された非特権モードを活用することはできません。

ノート: 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 logind's GetSessionByPID using its own pid as argument. See this thread and 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.
警告: 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] を見て下さい。

ユーザーユニットを書く

サンプル

以下は 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 を見て下さい。

ユースケース

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

ウィンドウマネージャのセッションにログインする代わりに、ユーザーセッションでデフォルトで 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

Once this is done, systemctl --user enable tmux.service, multiplexer.target and any services you created to be run by cruft.target and you should be set to go! Activated user-session@.service as described above, but be sure to remove the Conflicts=getty@tty1.service from 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!

ウィンドウマネージャ

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 としてリンクが作成され、ログイン時に起動できるようになります。リンクは手動で作成するのではなく、サービスを有効化することを推奨します。

参照