Need help understanding why calls to systemd do not work as intended #294
-
I was trying to develop a simple application to understand how to use this library and I actually enjoyed it quite a bit so far! The application just mimics My code looks like this #include <string>
#include <vector>
#include <fmt/format.h>
#include <sdbus-c++/sdbus-c++.h>
#include <CLI/App.hpp>
#include <CLI/Formatter.hpp>
#include <CLI/Config.hpp>
const std::string kDestination = "org.freedesktop.systemd1";
const std::string kObjectPath = "/org/freedesktop/systemd1";
const std::string kInterface = "org.freedesktop.systemd1.Manager";
const std::string kMethodStart = "StartUnit";
const std::string kMethodStop = "StopUnit";
const std::string kMethodRestart = "RestartUnit";
const std::string kMethodEnable = "EnableUnitFiles";
const std::string kMethodDisable = "DisableUnitFiles";
int main(int argc, char* argv[]) {
CLI::App app{"A simple program to start/stop/etc systemd services"};
std::string unit = "default";
std::string cmd_str = "default";
app.add_option("-u,--unit", unit, "Unit to do stuff to");
app.add_option("-c,--cmd", cmd_str, "What to do to the unit(start/stop/restart/enable/disable)");
CLI11_PARSE(app, argc, argv);
unit += ".service";
// Create proxy
std::unique_ptr<sdbus::IProxy> proxy = sdbus::createProxy(kDestination, kObjectPath);
// Invoke a function call
if (cmd_str == "start") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodStart).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Command returned {}\n", job);
} else if (cmd_str == "stop") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodStop).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Command returned {}\n", job);
} else if (cmd_str == "restart") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodRestart).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Command returned {}\n", job);
} else if (cmd_str == "enable") {
std::vector<sdbus::Struct<std::string, std::string, std::string>> changes;
bool carries_install_info;
proxy->callMethod(kMethodEnable)
.onInterface(kInterface)
.withArguments(std::vector<std::string>{unit}, false, true)
.storeResultsTo(changes, carries_install_info);
// fmt::print("Command returned {}\n", changes[0].get<0>());
} else if (cmd_str == "disable") {
std::vector<sdbus::Struct<std::string, std::string, std::string>> changes;
proxy->callMethod(kMethodDisable)
.onInterface(kInterface)
.withArguments(std::vector<std::string>{unit}, false)
.storeResultsTo(changes);
// fmt::print("Command returned {}\n", changes[0].get<0>());
} else {
fmt::print("your command is bullshit\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} when i run it (with sudo of course), the start/stop/restart commands work just fine, but enable and disable dont work. I have been trying this on the docker service on my machine
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
@akshatd Hello, good that you enjoy sdbus-c++! As per https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html, the order of the return values (output arguments) from As for |
Beta Was this translation helpful? Give feedback.
-
In case anyone is interested in the final piece of code, here it is #include <string>
#include <vector>
#include <tuple>
#include <fmt/format.h>
#include <fmt/ranges.h>
#include <sdbus-c++/sdbus-c++.h>
#include <CLI/App.hpp>
#include <CLI/Formatter.hpp>
#include <CLI/Config.hpp>
const std::string kDestination = "org.freedesktop.systemd1";
const std::string kObjectPath = "/org/freedesktop/systemd1";
const std::string kInterface = "org.freedesktop.systemd1.Manager";
const std::string kMethodStart = "StartUnit";
const std::string kMethodStop = "StopUnit";
const std::string kMethodRestart = "RestartUnit";
const std::string kMethodEnable = "EnableUnitFiles";
const std::string kMethodDisable = "DisableUnitFiles";
const std::string kMethodReload = "Reload";
int main(int argc, char* argv[]) {
CLI::App app{"A simple program to start/stop/etc systemd services"};
std::string unit = "default";
std::string cmd_str = "default";
app.add_option("-u,--unit", unit, "Unit to do stuff to");
app.add_option("-c,--cmd", cmd_str, "What to do to the unit(start/stop/restart/enable/disable)");
CLI11_PARSE(app, argc, argv);
unit += ".service";
// Create proxy
std::unique_ptr<sdbus::IProxy> proxy = sdbus::createProxy(kDestination, kObjectPath);
// Invoke a function call
if (cmd_str == "start") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodStart).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Job: {}\n", job);
} else if (cmd_str == "stop") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodStop).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Job: {}\n", job);
} else if (cmd_str == "restart") {
sdbus::ObjectPath job;
proxy->callMethod(kMethodRestart).onInterface(kInterface).withArguments(unit, "replace").storeResultsTo(job);
fmt::print("Job: {}\n", job);
} else if (cmd_str == "enable") {
bool carries_install_info;
std::vector<sdbus::Struct<std::string, std::string, std::string>> changes;
proxy->callMethod(kMethodEnable)
.onInterface(kInterface)
.withArguments(std::vector<std::string>{unit}, false, true)
.storeResultsTo(carries_install_info, changes);
proxy->callMethod(kMethodReload).onInterface(kInterface);
for (const std::tuple<std::string, std::string, std::string>& change : changes) {
fmt::print("Change: {}\n", change);
}
} else if (cmd_str == "disable") {
std::vector<sdbus::Struct<std::string, std::string, std::string>> changes;
proxy->callMethod(kMethodDisable)
.onInterface(kInterface)
.withArguments(std::vector<std::string>{unit}, false)
.storeResultsTo(changes);
proxy->callMethod(kMethodReload).onInterface(kInterface);
for (const std::tuple<std::string, std::string, std::string>& change : changes) {
fmt::print("Change: {}\n", change);
}
} else {
fmt::print("your command is bullshit\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
} |
Beta Was this translation helpful? Give feedback.
@akshatd Hello, good that you enjoy sdbus-c++! As per https://www.freedesktop.org/software/systemd/man/org.freedesktop.systemd1.html, the order of the return values (output arguments) from
EnableUnitFiles
call is: 1.carries_install_info
, 2.changes
. In your example, the order is inverted, hence sdbus-c++ is trying to find a vector of structures where a simple boolean lies (it fails entering the vector -- i.e. a container, hence such an error message). Try to invert both return values.As for
DisableUnitFiles
call, types and order of arguments seems fine to me. And there is no related failure. So it seems the call proceeded OK. The problem will probably lie somewhere else.