Inspect and safely use the systemd-logind D-Bus interface
By the end of this guide you will be able to query systemd-logind directly over the system bus, identify sessions and seats, inspect inhibitors, test whether a power operation is available, and enable or disable user lingering without guessing at object paths. The examples match the installed systemd 255 interface on this machine. Allow about 15 minutes if you are reading the output as you go.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a running systemd-logind service and the busctl command from systemd. Read-only queries normally need no elevated privileges. Changing lingering, seat assignments, reboot behaviour or power state is policy-controlled and may require authorisation. Do not run a power or termination method while experimenting: those methods can disrupt other users and can lose unsaved work.
Check the local version and the command you will use:
systemctl --version | head -2
command -v busctl
Expected output starts with systemd 255 on the reference installation and prints a path such as /usr/bin/busctl. If busctl is missing, install the systemd package using your distribution's normal package process before continuing.
Checkpoint 1: discover the manager interface
The service name is org.freedesktop.login1 and its manager object is /org/freedesktop/login1. Introspection asks the live daemon what methods and properties it exposes, so it is a better first check than relying on a copied interface listing.
busctl introspect org.freedesktop.login1 /org/freedesktop/login1
Look for the org.freedesktop.login1.Manager interface and entries such as ListSessions, ListSeats, ListInhibitors and NCurrentSessions. The installed manpage documents the same manager object, but an upgraded daemon can expose a different set of versioned members.
Checkpoint 2: list sessions, users and seats
Use the manager methods for a compact inventory. The first command returns session ID, numeric user ID, user name, seat ID and session object path. An empty seat field is valid for a session without an attached seat.
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager ListSessions
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager ListUsers
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager ListSeats
Typical output begins with a type signature such as a(susso) for sessions, followed by one or more records. Do not assume that the default seat is present: the manpage describes seat0 as the usual default, but persistent device assignments can move devices to other seats.
To inspect a known session after obtaining its ID, substitute the ID in the object path:
SESSION_ID="REPLACE_WITH_SESSION_ID"
busctl introspect org.freedesktop.login1 \
"/org/freedesktop/login1/session/$SESSION_ID"
Object paths are data from the daemon. Keep the quotes around a shell variable and do not construct a path from an untrusted value without checking it first.
Checkpoint 3: inspect inhibitors before changing power behaviour
Inhibitors explain why a shutdown, sleep or key action may be delayed or refused. List them before troubleshooting:
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager ListInhibitors
busctl get-property org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager BlockInhibited
busctl get-property org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager DelayInhibited
The list contains what is inhibited, the owning application, its reason, the mode, user ID and process ID. The two properties are colon-separated summaries for block and delay locks. An inhibitor is released when the creating process closes the returned file descriptor, so killing a process can remove a lock as a side effect.
Checkpoint 4: test capability without triggering it
The Can... methods report whether an operation is unavailable, allowed, denied or requires authorisation. They do not perform the operation. Test the action you intend to offer:
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager CanReboot
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager CanSuspend
Each result is one of na, yes, no or challenge. For example, challenge means the operation is supported but needs authorisation. Treat yes as permission for the current policy, not as a guarantee that hardware will complete suspend or reboot successfully.
Checkpoint 5: change user lingering, then verify it
User lingering keeps a user's runtime directory and permits their user services to continue after logout. It is persistent state, not a temporary session flag. Choose the numeric UID deliberately; do not paste a name where the D-Bus method expects an unsigned integer.
This example enables lingering for UID 1000. It changes system state and may require the polkit privilege org.freedesktop.login1.set-user-linger:
USER_UID="1000"
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager SetUserLinger u "$USER_UID" b true b false
The final boolean controls whether polkit may interactively ask for credentials. With false, a caller that needs a prompt will fail instead. Verify the result through the user object:
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager GetUser u "$USER_UID"
USER_PATH="REPLACE_WITH_OBJECT_PATH_FROM_THE_PREVIOUS_COMMAND"
busctl get-property org.freedesktop.login1 "$USER_PATH" \
org.freedesktop.login1.User Linger
Expected output for the property is b true. If you enabled this only for testing, undo it with the same method and b false:
busctl call org.freedesktop.login1 /org/freedesktop/login1 \
org.freedesktop.login1.Manager SetUserLinger u "$USER_UID" b false b false
Do not confuse lingering with a login session. It permits user services to run without a login, but it does not create an interactive session or attach a seat.
Common traps
- Wrong bus: logind is on the system bus. Adding
--userpoints at a different bus and will not query this service. - Wrong signature:
SetUserLingertakes an unsigned UID and two booleans, so the call includesu,b, andbbefore their values. - Unsafe experimentation:
TerminateSession,KillUser,PowerOffand related calls change or stop live work. Use inventory andCan...methods first. - Assumed privileges: polkit policy, multiple sessions and inhibitors affect authorisation. A successful introspection query does not grant permission to invoke every method.
- Interface drift: this guide targets systemd 255. Re-run introspection after a systemd upgrade and check the installed manpage for newly added members.
Done means
- You can name the service and manager object path.
- You can list sessions, users, seats and active inhibitors.
- You can test reboot or suspend availability without triggering it.
- You know that lingering is persistent, policy-controlled and reversible.
- You verified any change by reading the live
User.Lingerproperty.