closes 3286 wait for job remove signal youki-dev/youki #3299by cody-herbst $ man 5 org.freedesktop.systemd1

StartTransientUnit

D-Bus の StartTransientUnit メソッドを使うと、一時的な Unit を作成して起動できる。

method
StartTransientUnit(in s name, in s mode, in a(sv) properties, in a(sa(sv)) aux, out o job)

引数:

  • name: 作成する Unit の名前
  • mode: 起動モード。StartUnit() と同じ(replace|fail|isolate|ignore-dependencies|ignore-requirements)
  • properties: Unit のプロパティ一覧
  • aux: 補助的な Unit のプロパティ一覧
  • job: 作成された Job のオブジェクトパス

Job の完了を待つ

StartTransientUnit の呼び出しが成功しても、Job がキューにつまれているだけで、Unit の起動が完了したわけではない。 そのため、StartTransientUnit をよんだすぐに、Properties の変更を行おうとしても失敗する可能性がある。 これを回避するためにシグナルというのを使って Job の完了を待つ必要がある。 systemd の D-Bus では Subscribe() を呼ばないとシグナルが配送されないので、先に subscribe しておく。 StartTransientUnit の戻り値 job(オブジェクトパス)で Job を特定すると安全。

busctl でシグナルを監視することができる。

$ sudo busctl --system monitor org.freedesktop.systemd1
出力結果の例
$ sudo busctl --system monitor org.freedesktop.systemd1
Monitoring bus message stream.
‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1488314  Timestamp="Sat 2025-12-27 03:38:54.342384 UTC"
  Sender=:1.26174  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=UnitNew
  UniqueName=:1.26174
  MESSAGE "so" {
          STRING "demo-youki-scope.scope";
          OBJECT_PATH "/org/freedesktop/systemd1/unit/demo_2dyouki_2dscope_2escope";
  };

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1488315  Timestamp="Sat 2025-12-27 03:38:54.342805 UTC"
  Sender=:1.26174  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=JobNew
  UniqueName=:1.26174
  MESSAGE "uos" {
          UINT32 3725531;
          OBJECT_PATH "/org/freedesktop/systemd1/job/3725531";
          STRING "demo-youki-scope.scope";
  };

...

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1488322  Timestamp="Sat 2025-12-27 03:38:54.356210 UTC"
  Sender=:1.26174  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=JobRemoved
  UniqueName=:1.26174
  MESSAGE "uoss" {
          UINT32 3725531;
          OBJECT_PATH "/org/freedesktop/systemd1/job/3725531";
          STRING "demo-youki-scope.scope";
          STRING "done";
  };

...

‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1488327  Timestamp="Sat 2025-12-27 03:38:55.359587 UTC"
  Sender=:1.26174  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=UnitRemoved
  UniqueName=:1.26174
  MESSAGE "so" {
          STRING "demo-youki-scope.scope";
          OBJECT_PATH "/org/freedesktop/systemd1/unit/demo_2dyouki_2dscope_2escope";
  };

Job の完了は JobRemoved シグナルで通知される。結果は done だけでなく failed などもあるので、文字列を確認する。

$ sudo busctl --system monitor --match "type='signal',sender='org.freedesktop.systemd1',interface='org.freedesktop.systemd1.Manager',member='JobRemoved'"

Monitoring bus message stream.
‣ Type=signal  Endian=l  Flags=1  Version=1 Cookie=1488427  Timestamp="Sat 2025-12-27 03:43:43.293516 UTC"
  Sender=:1.26174  Path=/org/freedesktop/systemd1  Interface=org.freedesktop.systemd1.Manager  Member=JobRemoved
  UniqueName=:1.26174
  MESSAGE "uoss" {
          UINT32 3725702;
          OBJECT_PATH "/org/freedesktop/systemd1/job/3725702";
          STRING "demo-youki-scope.scope";
          STRING "done";
  };
$ sudo systemd-run --scope --unit=demo-youki-scope sleep 1
Running as unit: demo-youki-scope.scope; invocation ID: 6a076f0e68724b9d9e0685bdd9e4e5c5

これがよくまとまっていた。
https://pythonhosted.org/txdbus/dbus_overview.html