如何使用 Systemd -Dbus 介面啟動 .service 檔案?

如何使用 Systemd -Dbus 介面啟動 .service 檔案?

我需要使用 Systemd -D 匯流排介面呼叫服務檔。我認為使用g_dbus_connection_call_sync() 我們可以在D-Bus上進行通訊的方法我需要g_dbus_connection_call_sync()呼叫方法StartUnit();另外,我需要將 StartUnit() 參數模式指定為「replace」。

==================================================== = =========

#define SYSTEMD_MNGR_IF  "org.freedesktop.systemd1.Manager"
#define SYSTEMD_UNIT_IF  "org.freedesktop.systemd1.Unit"
#define SYSTEMD_SERVICE_IF  "org.freedesktop.systemd1.Service"
#define SYSTEMD_PROP_IF  "org.freedesktop.DBus.Properties"
#define SYSTEMD_SERVICE "org.freedesktop.systemd1"
#define SYSTEMD_OBJ "/org/freedesktop/systemd1"

GDBusConnection*   systemd_conn = NULL ;


    ret = g_dbus_connection_call_sync(systemd_conn,
            SYSTEMD_SERVICE,
            SYSTEMD_OBJ,
            SYSTEMD_MNGR_IF,
            "StartUnit",
            NULL,
            NULL,
            G_DBUS_CALL_FLAGS_NONE,
            -1,
            NULL,
            &error);

==================================================== = ================== 在哪裡傳遞替換參數?我需要定義一個新方法 StartUnit 嗎?

答案1

它不是您想要的原始 d-bus 解決方案,但它使用systemddbus 自己的包裝器,並針對 systemd 介面進行了調整。

我用sd_bus_call_method()使用使用libsystemd-dev

  • sd_bus* bus是一個被分配了 with 的對象sd_bus_default()

  • name是一個未轉義的單位名稱(即foo.service

  • method是其中之一"StartUnit""StopUnit""RestartUnit"

#include <systemd/sd-bus.h>

static void CallMethodSS(
    sd_bus* bus,
    const std::string& name,
    const std::string& method)
{
    sd_bus_error err = SD_BUS_ERROR_NULL;
    sd_bus_message* msg = nullptr;
    int r;

    r = sd_bus_call_method(bus,
        "org.freedesktop.systemd1",         /* <service>   */
        "/org/freedesktop/systemd1",        /* <path>      */
        "org.freedesktop.systemd1.Manager", /* <interface> */
        method.c_str(),                     /* <method>    */
        &err,                               /* object to return error in */
        &msg,                               /* return message on success */
        "ss",                               /* <input_signature (string-string)> */
        name.c_str(),  "replace" );         /* <arguments...> */

    if (r < 0)
    {
        std::string err_str("Could not send " + method +
                            " command to systemd for service: " + name +
                            ". Error: " + err.message );

        sd_bus_error_free(&err);
        sd_bus_message_unref(msg);
        throw exception(err_str);
    }

    // Extra stuff that might be useful:  display the response...
    char* response;
    r = sd_bus_message_read(msg, "o", &response);
    if (r < 0)
    {
      LogError("Failed to parse response message: %s\n", strerror(-r) );
    }

    sd_bus_error_free(&err);
    sd_bus_message_unref(msg);
}

systemd 開發人員在這裡給出了很好的解釋:

http://0pointer.de/blog/the-new-sd-bus-api-of-systemd.html

答案2

我的另一個答案使用另一個庫。這個答案是根據我的經驗sd_bus和閱讀 GDBusConnection 文件的猜測。

的簽名g_dbus_connection_call_sync是:

GVariant *  g_dbus_connection_call_sync(
    GDBusConnection    *connection,
    const gchar        *bus_name,
    const gchar        *object_path,
    const gchar        *interface_name,
    const gchar        *method_name,
    GVariant           *parameters,
    const GVariantType *reply_type,
    GDBusCallFlags      flags,
    gint                timeout_msec,
    GCancellable       *cancellable,
    GError            **error
);

GVariant* parameters這是這裡最有趣的部分。 Systemd"StartUnit" 方法有兩個參數:

      StartUnit(in  s name,  /* Name of the unit (foo.service) */
                in  s mode,  /* Mode of operation (replace) */
                out o job);

因此我們需要填充GVariant* parameters這兩個字串。我們可以透過以下方式做到這一點:

g_variant_new ("(ss)", "foo.service", "replace"),

"(ss)"格式字串,它指示g_variant_new建立一個包含兩個字串的變體。接下來的兩個參數是那些字串。

如果我要將其應用到您的程式碼中,我會得到以下結果:

    ret = g_dbus_connection_call_sync(
            systemd_conn,
            SYSTEMD_SERVICE,
            SYSTEMD_OBJ,
            SYSTEMD_MNGR_IF,
            "StartUnit",
            g_variant_new ("(ss)", "foo.service", "replace"),
            NULL,
            G_DBUS_CALL_FLAGS_NONE,
            -1,
            NULL,
            &error );

相關內容