web-dev-qa-db-ja.com

ヘッドレスシステムでセッションD-Busを共有するsystemdサービスを開始する

ヘッドレスLinuxシステムでセッション(システムではなく)D-Busを介して通信するサービスを開始するための支援が必要です。重要なのは、ヘッドレスシステムに誰もログインしないことです。

これまでのところ、D-Busデーモンを起動して、ログインしていないユーザー(「otheruser」)に代わって、3つの異なる端末でD-Bus通信をテストすることができました。

最初のターミナルで、「otheruser」のD-Busデーモンを開始します。

$ Sudo -u otheruser dbus-daemon --session --print-address 1
unix:abstract=/tmp/dbus-a5cU7r4IHc,guid=6c0a9bbfd02f5f68da0fe32f5a5e0a48

2番目の端末で、上記のDBUS_SESSION_BUS_ADDRESS応答を使用してD-Busサーバーアプリケーションを起動します。

$ Sudo -u otheruser DBUS_SESSION_BUS_ADDRESS="unix:abstract=/tmp/dbus-a5cU7r4IHc,guid=6c0a9bbfd02f5f68da0fe32f5a5e0a48" /usr/bin/my-dbus-service

次に、3番目のターミナルで接続をテストできます。

$ Sudo -u otheruser DBUS_SESSION_BUS_ADDRESS="unix:abstract=/tmp/dbus-a5cU7r4IHc,guid=6c0a9bbfd02f5f68da0fe32f5a5e0a48" gdbus introspect --session --dest com.mycompany.myappname --object-path /com/mycompany/interface

しかし、systemdを介してD-BusサーバーアプリケーションといくつかのクライアントD-Busサービスを開始したいと思います。 systemdを介してD-Busセッションを開始して、そのDBUS_SESSION_BUS_ADDRESS環境変数が「otheruser」のD-Busサーバーおよびクライアントサービスに伝達されるようにするにはどうすればよいですか?

1つの可能な解決策は、dbus-daemonの出力を「somefile」にパイプし、D-Busサーバーとクライアントを起動する前にDBUS_SESSION_BUS_ADDRESS = $(cat somefile)を設定することです。これは私には少しぎこちないようです。特に、systemdサービスファイルのsystem D-Bus接続の「Busname」ディレクティブに魔法があることに気づいているためです。これらのsystemdサービスがセッションD-Busインターフェースと通信できるように、「otheruser」のsystemdサービスを適切に開始するにはどうすればよいですか?

12
Ole Wolf

これを機能させるにはいくつかのものが必要です。

  1. 起動時にユーザーログインなしでユーザーサービスを実行できるようにします(systemdリンガー)。
  2. Systemdが割り当てるD-Busソケットを指定するsystemdソケットファイル。
  3. 起動するD-Busセッションバスを起動するsystemdサービス。その後、他のsystemdサービス用にDBUS_SESSION_BUS_ADDRESS環境変数を設定します。
  4. Systemd my-dbus-client.serviceファイルがType=dbusであることを確認するか、dbus.socketユニットに依存して、dbusセッションバスソケットが割り当てられ、dubセッションサービスがまだ開始されていない場合は開始するようにします。 。

まず、特定のユーザーのSystemdサービスをログインなしで起動時に開始するには、systemdユーザーの残存を有効にする必要があります。これは、ユーザーに対して有効にするように構成するときに、rootとして一度だけ実行する必要があります。

# loginctl enable-linger otheruser

次に、Debianベースのシステムを使用している場合、次の2つのステップでは、パッケージdbus-user-sessionパッケージをインストールするだけです。

# apt-get install dbus-user-session

他のディストリビューションを使用している場合、これを手動で実行するか、単にそれがどのように機能するかを理解したいだけです。それ以外の場合は、dbus.serviceおよびdbus.socketの作成をスキップします。

次の内容のファイル/usr/lib/systemd/user/dbus.socketを作成します(一部のディストリビューションでは、ユーザーディレクトリは/libではなく/usr/libの下にある場合があります)。

[Unit]
Description=D-Bus User Message Bus Socket

[Socket]
ListenStream=%t/bus
ExecStartPost=-/bin/systemctl --user set-environment DBUS_SESSION_BUS_ADDRESS=unix:path=%t/bus

[Install]
WantedBy=sockets.target
Also=dbus.service

すべてのサービスへのDBUS_SESSION_BUS_ADDRESSの伝播は、あなたの主な関心事でしたが、以下のExecPostStart行で対処されます-以降のすべてのサービスがそのセットを持ちます。

%tXDG_RUNTIME_DIRに置き換えられます-systemdによって作成され、ユーザーセッションに固有のファイルを挿入できる/runの下の一時ディレクトリ。このソケットを別の場所に作成したい場合は、作成できない理由はありません。それがどこか一時的なものであること、または再起動/セッションのティアダウン時にクリーンアップされることを確認してください。

私はdbus unixソケットを抽象ソケットにしようとしていくつかの問題を抱えていました-何らかの理由でsystemdはunix:abstract=または@プレフィックスの形式が好きではないようです。

次の内容でファイル/usr/lib/systemd/user/dbus.serviceを作成します。

[Unit]
Description=D-Bus User Message Bus
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

Systemdが舞台裏で既に作成したunixソケットをdbus-daemonに渡すためのちょっとした魔法があります。 Systemdはdbus.socketからの情報を使用してソケットを作成し、そのファイル記述子は環境変数LISTEN_FDSに設定され、dbus-daemonに渡されます。上記の特別なオプションにより、dbus-daemonは、新しいファイル記述子を作成する代わりに、渡されたファイル記述子を使用します。これにより、dbusクライアントは、存在しないソケットを心配することなく、dbus-daemonの開始と並行して開始できます。

最後に、独自のsystemdユーザーサービスを作成し、タイプをType=dbusに設定するか、BusName=をこのサービスによって登録されるdbusサービス名の1つの名前に設定するか、またはUnitセクションでRequires=dbus.socketが指定されていることを確認してください。次に例を示します。

[Unit]
Description=Config Server Startup

[Service]
Type=dbus
BusName=com.example.app.configuree
ExecStart=/opt/example/app/configuration_server
Restart=on-failure

[Install]
WantedBy=default.target

いくつかの場所のいずれかに配置できます。-$HOME/.config/systemd/user-/usr/lib/systemd/user

systemctl --user enable <service name>でサービスを有効にして再起動すると、すべてが機能するはずです。


参照:

  • man loginctl for linger
  • man pam_systemd for XDG_RUNTIME_DIR info
  • Type = dbus、BusName =のman systemd.service、およびdbus.socketへの暗黙の依存関係
  • man sd_listen_fds LISTEN_FDS環境変数に関する情報
  • https://wiki.archlinux.org/index.php/Systemd/User -systemdユーザーセッションに関する一般情報
14
Keithel