サービスの状態が変わったときにスクリプトを実行する方法はありますか?

サービスの状態が変わったときにスクリプトを実行する方法はありますか?

重要なサービスが停止したら、スクリプトを実行して自分に知らせるか、事前定義されたタスクを実行してサービスを復元できるように、実行中のサービスの状態に接続したいと思います。

答え1

いいえどの提供する。 systemd 管理者の dbus インターフェイスは、このタイプのグローバル通知を提供しません。グローバルにトリガされる信号を探している場合、管理者の信号はパフォーマンス上の理由でわずかに制限されます。

$ busctl introspect org.freedesktop.systemd1 \
    /org/freedesktop/systemd1 \
    org.freedesktop.systemd1.Manager \
    | grep signal
.JobNew                                   signal    uos              -                -
.JobRemoved                               signal    uoss             -                -
.Reloading                                signal    b                -                -
.StartupFinished                          signal    tttttt           -                -
.UnitFilesChanged                         signal    -                -                -
.UnitNew                                  signal    so               -                -
.UnitRemoved                              signal    so               -                -

完全なインターフェイスはここで見ることができます:

https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html

ただし、特定のサービスの状態が変更されたかどうかを知りたい場合は、その特定のサービスに参加してください。例: sshd.service:

$ busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/sshd_2eservice \
    org.freedesktop.DBus.Properties 
NAME                            TYPE      SIGNATURE RESULT/VALUE FLAGS
.Get                            method    ss        v            -
.GetAll                         method    s         a{sv}        -
.Set                            method    ssv       -            -
.PropertiesChanged              signal    sa{sv}as  -            -

.PropertiesChanged属性が変更されるたびにシグナルが発生します。

興味を持っている可能性のあるプロパティはまたはインターフェイスにあります.ActiveState.SubStateorg.freedesktop.systemd1.Unit

$ busctl introspect \
    org.freedesktop.systemd1 \
    /org/freedesktop/systemd1/unit/sshd_2eservice \
    org.freedesktop.systemd1.Unit
...
.ActiveState    property  s         "active"         emits-change
.SubState       property  s         "running"        emits-change

それでは、どのように購読してこのデータを入手できますか?どのようにスクリプトを書くのかわかりませんが、#include <systemd/sd-bus.h>sd-bus API()を使ってCで何かを書いてみましょう。これには次のステップが必要です。

  • オープンバス:
int r = sd_bus_default_system(&m_bus);
  • 特定のユニットの変更を購読してください。
    sd_bus_match_signal(
        m_bus,
        NULL, // slot
        NULL, // sender
        "/org/freedesktop/systemd1/unit/sshd_2eservice", // path
        "org.freedesktop.DBus.Properties", // interface
        "PropertiesChanged", // member
        callback, // callback
        NULL // userdata
    );

    sd_bus_match_signal(
        m_bus,
        NULL,
        NULL,
        "/org/freedesktop/systemd1/unit/network_2etarget",
        "org.freedesktop.DBus.Properties",
        "PropertiesChanged",
        callback,
        NULL
    );
  • 変更に応じて新しい状態を取得します。
int callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
{
    sd_bus_error err = SD_BUS_ERROR_NULL;
    char* msg = NULL;
    int r;

    r = sd_bus_get_property_string(m_bus,
        "org.freedesktop.systemd1",
        sd_bus_message_get_path(m), // (/org/freedesktop/systemd1/unit/sshd_2eservice)
        "org.freedesktop.systemd1.Unit",
        "ActiveState",
        &err,
        &msg);

    if (r < 0) { /* Error */ }

    sd_bus_error_free(&err);

    printf("Property change, state is: %s\n", msg);
    free (msg);
}

関連する答えは次のとおりです。 https://stackoverflow.com/questions/61940461/how-to-get-the-state-of-a-service-with-sd-bus/62038047#62038047

答え2

簡単な可能性はログ出力を追跡することですjournalctl -f。簡単な解析のためにjsonを含むいくつかの出力フォーマットオプションがあります。

関連情報