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 솔루션은 아니지만 systemd
systemd 인터페이스에 맞게 조정된 dbus 주변의 자체 래퍼를 사용합니다.
나는 사용한다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 개발자의 좋은 설명은 다음과 같습니다.
답변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 );