g_dbus_connection_call_sync()
Systemd -D バス インターフェースを使用してサービス ファイルを呼び出す必要があります。メソッドを使用して 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
割り当てられたオブジェクトです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"
メソッドは 2 つのパラメータを取ります。
StartUnit(in s name, /* Name of the unit (foo.service) */
in s mode, /* Mode of operation (replace) */
out o job);
したがって、これら 2 つの文字列を入力する必要がありますGVariant* parameters
。これは次のように実行できます。
g_variant_new ("(ss)", "foo.service", "replace"),
は"(ss)"
フォーマット文字列で、g_variant_new
2 つの文字列を含むバリアントを作成するように指示します。次の 2 つのパラメータはそれらの文字列です。
これをあなたのコードに適用すると、次のようになります。
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 );