Created
May 30, 2023 15:28
-
-
Save mikroskeem/f014af9ba51f12b47b4e14498ae3772a to your computer and use it in GitHub Desktop.
Example Lua script interfacing with systemd D-BUS service
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- nix-shell -p luajit luajitPackages.ldbus luajitPackages.inspect | |
local ldbus = require("ldbus") | |
local inspect = require("inspect") | |
local conn = assert(ldbus.bus.get("system"), "System bus connection failed") | |
function do_method_call(conn, destination, path, iface, method_name, args, f) | |
local msg = assert(ldbus.message.new_method_call(destination, path, iface, method_name), "Failed to create message") | |
local iter = ldbus.message.iter.new() | |
msg:iter_init_append(iter) | |
-- Pack arguments | |
for idx, v in ipairs(args or {}) do | |
assert(iter:append_basic(v), "Failed to append argument " .. tostring(idx)) | |
end | |
local reply, err = conn:send_with_reply_and_block(msg) | |
if err then | |
error("Method call failed: " .. err) | |
end | |
assert(reply, "Nil method call response") | |
assert(reply:iter_init(iter), "Message has no arguments") | |
-- XXX: if msg or reply fall out of scope, we'll get segmentation fault sooner or later... | |
return f(iter, msg, reply) | |
end | |
-- ListUnits(out a(ssssssouso) units); | |
local ret = do_method_call(conn, "org.freedesktop.systemd1" , "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager" , "ListUnits", nil, function(iter, msg, reply) | |
local array_iter = iter:recurse() | |
local struct_names = { | |
"primary_unit_name", | |
"description", | |
"load_state", | |
"active_state", | |
"sub_state", | |
"follwing_unit", | |
"unit_object_path", | |
"queued_job_id", | |
"job_type", | |
"job_object_path", | |
} | |
local all_units = {} | |
repeat | |
assert(array_iter:get_arg_type() == ldbus.types.struct, "Expected structure") | |
assert(array_iter:get_signature() == "(ssssssouso)", "Expected structure") | |
local struct_iter = array_iter:recurse() | |
local i = 1 | |
local obj = {} | |
repeat | |
local t = struct_iter:get_signature() | |
local v = struct_iter:get_basic() | |
local name = struct_names[i] | |
obj[name] = v | |
i = i + 1 | |
until not struct_iter:next() | |
table.insert(all_units, obj) | |
until not array_iter:next() | |
return all_units | |
end) | |
print(inspect(ret)) | |
-- RestartUnit(in s name, in s mode, out o job) | |
local ret2 = do_method_call(conn, "org.freedesktop.systemd1" , "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager" , "RestartUnit", {"chronyd.service", "fail"}, function(iter, msg, reply) | |
return "ok" | |
end) | |
print(inspect(ret2)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Self-note:
os.execute({"systemctl", "restart", "chronyd.service"})
might be a better idea after all...