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 솔루션은 아니지만 systemdsystemd 인터페이스에 맞게 조정된 dbus 주변의 자체 래퍼를 사용합니다.

나는 사용한다sd_bus_call_method()사용 libsystemd-dev:

  • sd_bus* buswith로 할당된 객체입니다.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_busGDBusConnection 문서를 읽고 읽은 경험을 바탕으로 한 추측입니다 .

서명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 );

관련 정보