Skip to content

Instantly share code, notes, and snippets.

@mikroskeem
Created May 30, 2023 15:28
Show Gist options
  • Save mikroskeem/f014af9ba51f12b47b4e14498ae3772a to your computer and use it in GitHub Desktop.
Save mikroskeem/f014af9ba51f12b47b4e14498ae3772a to your computer and use it in GitHub Desktop.
Example Lua script interfacing with systemd D-BUS service
-- 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))
@mikroskeem
Copy link
Author

Self-note: os.execute({"systemctl", "restart", "chronyd.service"}) might be a better idea after all...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment