ORG.FREEDESKTOP.SYSTEMD1(5)
โจ NAME โจ
org.freedesktop.systemd1 โ the D-Bus interface of systemd ๐
Bestie, this is the manual page for org.freedesktop.systemd1(5), and it's giving main character energy for systemd's D-Bus APIs. ๐ซถ
๐ธ INTRODUCTION ๐ธ
okay so first things first: systemd(1) and its auxiliary daemons expose a number of APIs over D-Bus. This page only describes the various APIs exposed by the system and service manager itself. It does not cover the auxiliary daemons. periodt. ๐
The service manager exposes a number of objects on the bus: one Manager object as a central entry point for clients along with individual objects for each unit and for each queued job. The unit objects implement a generic Unit interface as well as a type-specific interface. For example, service units implement both org.freedesktop.systemd1.Unit and org.freedesktop.systemd1.Service. The manager object can list unit and job objects or directly convert a unit name or job identifier to a bus path of the corresponding D-Bus object. no cap, it's literally that flexible. โจ
Properties exposing time values are usually encoded in microseconds (ฮผs) on the bus, even if their corresponding settings in the unit files are in seconds. so like, watch out for that little unit conversion moment bestie, it's lowkey important. ๐ญ
PID 1 uses polkit[1] to allow access to privileged operations for unprivileged processes. Some operations (such as shutdown/reboot/suspend) are also available through the D-Bus API of logind, see org.freedesktop.login1(5). iconic behavior, honestly. ๐
๐ THE MANAGER OBJECT ๐
The main entry point object is available on the fixed /org/freedesktop/systemd1 object path:
okay so here's the whole entire D-Bus interface block for the Manager object โ every method, every signal, exactly how it lands when you point a bus at it. no filtering, no skipping, we're reading the whole menu together bestie ๐ซถ
node /org/freedesktop/systemd1 {
interface org.freedesktop.systemd1.Manager {
methods:
GetUnit(in s name,
out o unit);
GetUnitByPID(in u pid,
out o unit);
GetUnitByInvocationID(in ay invocation_id,
out o unit);
GetUnitByControlGroup(in s cgroup,
out o unit);
GetUnitByPIDFD(in h pidfd,
out o unit,
out s unit_id,
out ay invocation_id);
LoadUnit(in s name,
out o unit);
StartUnit(in s name,
in s mode,
out o job);
StartUnitWithFlags(in s name,
in s mode,
in t flags,
out o job);
StartUnitReplace(in s old_unit,
in s new_unit,
in s mode,
out o job);
StopUnit(in s name,
in s mode,
out o job);
ReloadUnit(in s name,
in s mode,
out o job);
RestartUnit(in s name,
in s mode,
out o job);
TryRestartUnit(in s name,
in s mode,
out o job);
ReloadOrRestartUnit(in s name,
in s mode,
out o job);
ReloadOrTryRestartUnit(in s name,
in s mode,
out o job);
EnqueueUnitJob(in s name,
in s job_type,
in s job_mode,
out u job_id,
out o job_path,
out s unit_id,
out o unit_path,
out s job_type,
out a(uosos) affected_jobs);
EnqueueUnitJobMany(in as units,
in s job_type,
in s job_mode,
in t flags,
out a(uosos) jobs);
KillUnit(in s name,
in s whom,
in i signal);
KillUnitSubgroup(in s name,
in s whom,
in s subgroup,
in i signal);
QueueSignalUnit(in s name,
in s whom,
in i signal,
in i value);
CleanUnit(in s name,
in as mask);
FreezeUnit(in s name);
ThawUnit(in s name);
ResetFailedUnit(in s name);
SetUnitProperties(in s name,
in b runtime,
in a(sv) properties);
BindMountUnit(in s name,
in s source,
in s destination,
in b read_only,
in b mkdir);
MountImageUnit(in s name,
in s source,
in s destination,
in b read_only,
in b mkdir,
in a(ss) options);
RefUnit(in s name);
UnrefUnit(in s name);
StartTransientUnit(in s name,
in s mode,
in a(sv) properties,
in a(sa(sv)) aux,
out o job);
GetUnitProcesses(in s name,
out a(sus) processes);
AttachProcessesToUnit(in s unit_name,
in s subcgroup,
in au pids);
RemoveSubgroupFromUnit(in s unit_name,
in s subcgroup,
in t flags);
AbandonScope(in s name);
GetJob(in u id,
out o job);
GetJobAfter(in u id,
out a(usssoo) jobs);
GetJobBefore(in u id,
out a(usssoo) jobs);
CancelJob(in u id);
ClearJobs();
ResetFailed();
SetShowStatus(in s mode);
ListUnits(out a(ssssssouso) units);
ListUnitsFiltered(in as states,
out a(ssssssouso) units);
ListUnitsByPatterns(in as states,
in as patterns,
out a(ssssssouso) units);
ListUnitsByNames(in as names,
out a(ssssssouso) units);
ListJobs(out a(usssoo) jobs);
Subscribe();
Unsubscribe();
Dump(out s output);
DumpUnitsMatchingPatterns(in as patterns,
out s output);
DumpByFileDescriptor(out h fd);
DumpUnitsMatchingPatternsByFileDescriptor(in as patterns,
out h fd);
Reload();
@org.freedesktop.DBus.Method.NoReply("true")
Reexecute();
@org.freedesktop.systemd1.Privileged("true")
Exit();
@org.freedesktop.systemd1.Privileged("true")
Reboot();
@org.freedesktop.systemd1.Privileged("true")
SoftReboot(in s new_root);
@org.freedesktop.systemd1.Privileged("true")
PowerOff();
@org.freedesktop.systemd1.Privileged("true")
Halt();
@org.freedesktop.systemd1.Privileged("true")
KExec();
@org.freedesktop.systemd1.Privileged("true")
SwitchRoot(in s new_root,
in s init);
SetEnvironment(in as assignments);
UnsetEnvironment(in as names);
UnsetAndSetEnvironment(in as names,
in as assignments);
EnqueueMarkedJobs(out ao jobs);
ListUnitFiles(out a(ss) unit_files);
ListUnitFilesByPatterns(in as states,
in as patterns,
out a(ss) unit_files);
GetUnitFileState(in s file,
out s state);
EnableUnitFiles(in as files,
in b runtime,
in b force,
out b carries_install_info,
out a(sss) changes);
DisableUnitFiles(in as files,
in b runtime,
out a(sss) changes);
EnableUnitFilesWithFlags(in as files,
in t flags,
out b carries_install_info,
out a(sss) changes);
DisableUnitFilesWithFlags(in as files,
in t flags,
out a(sss) changes);
DisableUnitFilesWithFlagsAndInstallInfo(in as files,
in t flags,
out b carries_install_info,
out a(sss) changes);
ReenableUnitFiles(in as files,
in b runtime,
in b force,
out b carries_install_info,
out a(sss) changes);
LinkUnitFiles(in as files,
in b runtime,
in b force,
out a(sss) changes);
PresetUnitFiles(in as files,
in b runtime,
in b force,
out b carries_install_info,
out a(sss) changes);
PresetUnitFilesWithMode(in as files,
in s mode,
in b runtime,
in b force,
out b carries_install_info,
out a(sss) changes);
MaskUnitFiles(in as files,
in b runtime,
in b force,
out a(sss) changes);
UnmaskUnitFiles(in as files,
in b runtime,
out a(sss) changes);
RevertUnitFiles(in as files,
out a(sss) changes);
SetDefaultTarget(in s name,
in b force,
out a(sss) changes);
GetDefaultTarget(out s name);
PresetAllUnitFiles(in s mode,
in b runtime,
in b force,
out a(sss) changes);
AddDependencyUnitFiles(in as files,
in s target,
in s type,
in b runtime,
in b force,
out a(sss) changes);
GetUnitFileLinks(in s name,
in b runtime,
out as links);
SetExitCode(in y number);
LookupDynamicUserByName(in s name,
out u uid);
LookupDynamicUserByUID(in u uid,
out s name);
GetDynamicUsers(out a(us) users);
DumpUnitFileDescriptorStore(in s name,
out a(suuutuusu) entries);
signals:
UnitNew(s id,
o unit);
UnitRemoved(s id,
o unit);
JobNew(u id,
o job,
s unit);
JobRemoved(u id,
o job,
s unit,
s result);
๐ methods:
okay first vibe check: this is a LOT of methods. like a lot lot. and every single one is written as Name(in <type> <arg>, ..., out <type> <arg>) so you always clock what goes in and what comes back out. the type letters (s, o, u, b, t, i, y, h, ay, as, au, ao, a(sv), a(sa(sv)), and the stacked-tuple ones like a(ssssssouso)) are doing SO much heavy lifting in there, so read them carefully before you call anything, bestie ๐ซถ
- the unit lookup crew โ
GetUnit,GetUnitByPID,GetUnitByInvocationID,GetUnitByControlGroup,GetUnitByPIDFD,LoadUnit. all of them hand you back an object path (out o unit)โฆ exceptGetUnitByPIDFD, which is extra and gives you three things:out o unit,out s unit_id,out ay invocation_id. not me being obsessed with a triple return ๐ - the job starters โ
StartUnit,StartUnitWithFlags,StartUnitReplace,StopUnit,ReloadUnit,RestartUnit,TryRestartUnit,ReloadOrRestartUnit,ReloadOrTryRestartUnit. every single one takesin s name+in s modeand gives youout o job.StartUnitWithFlagsis the one that also takesin t flags, andStartUnitReplaceswaps inin s old_unit+in s new_unitinstead of a single name. she's different, she's versatile โจ - enqueue era โ
EnqueueUnitJobtakesin s name,in s job_type,in s job_modeand returnsout u job_id,out o job_path,out s unit_id,out o unit_path,out s job_type, plusout a(uosos) affected_jobs(thorough queen). thenEnqueueUnitJobManytakesin as units,in s job_type,in s job_mode,in t flagsand returnsout a(uosos) jobs. - the kill/signal trio โ
KillUnit(in s name,in s whom,in i signal),KillUnitSubgroup(same but with an extrain s subgroup), andQueueSignalUnit(same but with an extrain i value). ๐ - unit housekeeping โ
CleanUnit(in as mask),FreezeUnit,ThawUnit,ResetFailedUnit,SetUnitProperties(in b runtime+in a(sv) properties),BindMountUnit(in s source,in s destination,in b read_only,in b mkdir),MountImageUnit(that exact same shape plusin a(ss) options),RefUnit,UnrefUnit. - transient + process stuff โ
StartTransientUnit(in s name,in s mode,in a(sv) properties,in a(sa(sv)) aux,out o jobโ that nesteda(sa(sv))is a whole vibe ngl),GetUnitProcesses(in s name,out a(sus) processes),AttachProcessesToUnit(in s unit_name,in s subcgroup,in au pids),RemoveSubgroupFromUnit(in s unit_name,in s subcgroup,in t flags),AbandonScope(in s name). - jobs o'clock โ
GetJob(in u idโout o job),GetJobAfterandGetJobBefore(bothin u idโout a(usssoo) jobs),CancelJob(in u id),ClearJobs,ResetFailed, andSetShowStatus(in s mode). - listing era โ
ListUnits,ListUnitsFiltered(in as states),ListUnitsByPatterns(in as states,in as patterns),ListUnitsByNames(in as names) โ every one of them returnsout a(ssssssouso) units, which is a stacked signature, ok? and thenListJobswithout a(usssoo) jobs. ๐ฆ - bus chit-chat โ
Subscribe,Unsubscribe,Dump(out s output),DumpUnitsMatchingPatterns(in as patternsโout s output),DumpByFileDescriptor(out h fd),DumpUnitsMatchingPatternsByFileDescriptor(in as patternsโout h fd). - big moves โ
Reload,Reexecute,Exit,Reboot,SoftReboot(in s new_root),PowerOff,Halt,KExec,SwitchRoot(in s new_root,in s init). and listen:Reexecuteis sitting under@org.freedesktop.DBus.Method.NoReply("true")โ no reply comes back, that's literally the point of the annotation. meanwhileExit,Reboot,SoftReboot,PowerOff,Halt,KExecandSwitchRootall carry@org.freedesktop.systemd1.Privileged("true")above them. main character energy only ๐ - environment โ
SetEnvironment(in as assignments),UnsetEnvironment(in as names),UnsetAndSetEnvironment(in as names,in as assignments), andEnqueueMarkedJobs(out ao jobs). - unit file central โ
ListUnitFiles(out a(ss) unit_files),ListUnitFilesByPatterns(in as states,in as patternsโout a(ss) unit_files),GetUnitFileState(in s fileโout s state),EnableUnitFiles(in as files,in b runtime,in b forceโout b carries_install_info+out a(sss) changes),DisableUnitFiles(in as files,in b runtimeโout a(sss) changes),EnableUnitFilesWithFlags(in as files,in t flagsโout b carries_install_info+out a(sss) changes),DisableUnitFilesWithFlags(in as files,in t flagsโout a(sss) changes),DisableUnitFilesWithFlagsAndInstallInfo(that same shape but without b carries_install_infoback in the outs),ReenableUnitFiles(in as files,in b runtime,in b forceโout b carries_install_info+out a(sss) changes),LinkUnitFiles(in as files,in b runtime,in b forceโout a(sss) changes),PresetUnitFiles(in as files,in b runtime,in b forceโout b carries_install_info+out a(sss) changes),PresetUnitFilesWithMode(that plus anin s modeat the front),MaskUnitFiles(in as files,in b runtime,in b forceโout a(sss) changes),UnmaskUnitFiles(in as files,in b runtimeโout a(sss) changes), andRevertUnitFiles(in as filesโout a(sss) changes). yes, they're all extremely similar and yes, theruntime/forcepair is doing a lot of repeating. iykyk ๐ธ - targets + deps โ
SetDefaultTarget(in s name,in b forceโout a(sss) changes),GetDefaultTarget(out s name),PresetAllUnitFiles(in s mode,in b runtime,in b forceโout a(sss) changes),AddDependencyUnitFiles(in as files,in s target,in s type,in b runtime,in b forceโout a(sss) changes),GetUnitFileLinks(in s name,in b runtimeโout as links). - the stragglers โ
SetExitCode(in y number),LookupDynamicUserByName(in s nameโout u uid),LookupDynamicUserByUID(in u uidโout s name),GetDynamicUsers(out a(us) users), andDumpUnitFileDescriptorStore(in s nameโout a(suuutuusu) entries). that last signature. that's it, that's the whole thought. ๐ญ
๐ฃ signals:
four of them, four signatures, all spelled out exactly as they arrive โ no edits, no trimming:
UnitNew(s id, o unit)โ takess idando unit.UnitRemoved(s id, o unit)โ takess idando unit.JobNew(u id, o job, s unit)โ takesu id,o job,s unit.JobRemoved(u id, o job, s unit, s result)โ takesu id,o job,s unit, and an extras result. ๐ซถ
and yeah, that's the entire method roster and the signal squad, all sitting right there inside interface org.freedesktop.systemd1.Manager { under node /org/freedesktop/systemd1 { โ no cap, nothing skipped, every single in, every single out, every annotation accounted for ๐
...and it keeps going, because of course it does. Here's the rest of the signal block, plus the moment this whole thing pivots into the property zone:
StartupFinished(t firmware,
t loader,
t kernel,
t initrd,
t userspace,
t total);
UnitFilesChanged();
Reloading(b active);
properties:
Okay so StartupFinished() rolls up to you with six separate t-typed numbers โ firmware, loader, kernel, initrd, userspace, and total โ so if you're the kind of person who wants the whole boot timeline in one shot instead of doom-scrolling a million individual timestamp properties, this is the signal for you. Then UnitFilesChanged() with no arguments at all (it's just vibing, zero params), and Reloading(b active) handing you a single b-typed active. And then, boom, properties: โ we're in the property section now, bestie, and it's a long one. Buckle up. ๐
โจ Properties โจ
๐ฆ The "who even am I" block
Identity crisis, but make it const. Every one of these is a read-only string and every one carries @org.freedesktop.DBus.Property.EmitsChangedSignal("const"):
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Version = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Features = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Virtualization = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ConfidentialVirtualization = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Architecture = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Tainted = '...';
That "const" annotation is the way the interface says "this one does not emit a changed signal" โ so don't sit there waiting for a notification that is never, ever coming. ๐ซถ Six strings, all <pink>readonly</pink>, all s, all with the exact same annotation line in front of them.
โฐ The timestamp cinematic universe
This is the part where I need you to stay with me, because it is a lot of t-typed properties and they all have "const" on them:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t FirmwareTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t FirmwareTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LoaderTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LoaderTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t KernelTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t KernelTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UserspaceTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UserspaceTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t FinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t FinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t ShutdownStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t ShutdownStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t ShutdownFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t ShutdownFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownLateStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownLateStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownLateFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PreviousShutdownLateFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SecurityStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SecurityStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SecurityFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SecurityFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t GeneratorsStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t GeneratorsStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t GeneratorsFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t GeneratorsFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t UnitsLoadTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDSecurityStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDSecurityStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDSecurityFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDSecurityFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDGeneratorsStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDGeneratorsStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDGeneratorsFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDGeneratorsFinishTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDUnitsLoadStartTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDUnitsLoadStartTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDUnitsLoadFinishTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t InitRDUnitsLoadFinishTimestampMonotonic = ...;
Notice the pattern, bestie, because it's genuinely the whole trick: every single one of these has a ...Monotonic twin right after it. Firmware, Loader, Kernel, InitRD, Userspace, Finish, ShutdownStart, ShutdownFinish, then a whole flashback arc of PreviousShutdownStart, PreviousShutdownFinish, PreviousShutdownLateStart, PreviousShutdownLateFinish, then Security, Generators, UnitsLoadStart, UnitsLoadFinish, UnitsLoad, and then the InitRD remix of InitRDSecurity, InitRDGenerators, InitRDUnitsLoadStart, InitRDUnitsLoadFinish โ all of them readonly t ... = ...; with the "const" annotation glued on top. Fifty-four lines of pure timestamp realness. No notes. ๐
๐๏ธ The two you can actually write to
Okay so unlike everything above, these two are <hotpink>readwrite</hotpink> โ and both are marked @org.freedesktop.systemd1.Privileged("true") with EmitsChangedSignal("false"):
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite s LogLevel = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite s LogTarget = '...';
Two s-typed strings, LogLevel and LogTarget. They're readwrite, so yeah you can set them, but Privileged("true") is sitting right there telling you this is a privileged operation โ so don't act surprised when unprivileged you gets told no. ๐
๐ข The counters (and one array, and one double, and one list)
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NNames = ...;
readonly u NFailedUnits = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NJobs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NInstalledJobs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NFailedJobs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly at TransactionsWithOrderingCycle = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly d Progress = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as Environment = ['...', ...];
Read that carefully because it's sneaky: NNames has the "false" annotation above it, and then NFailedUnits does not โ it's the one bare line in this little cluster, no annotation of its own. Keep it that way, don't "fix" it, it's literally the source. Everything else here is "false" + readonly.
Type check while we're here: u for NNames, NFailedUnits, NJobs, NInstalledJobs, NFailedJobs; at for TransactionsWithOrderingCycle; d for Progress; as for Environment. Four different type letters in one neighbourhood, we love range. ๐
๐ต๏ธ The assorted-facts corner
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ConfirmSpawn = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b ShowStatus = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UnitPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s DefaultStandardOutput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s DefaultStandardError = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s WatchdogDevice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogLastPingTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogLastPingTimestampMonotonic = ...;
Watch the annotations here, because they alternate and it's so easy to glaze over: ConfirmSpawn is "const", ShowStatus is "false", UnitPath is "const", DefaultStandardOutput is "const", DefaultStandardError is "const", WatchdogDevice is "const", then both WatchdogLastPingTimestamp and its ...Monotonic twin drop back to "false". Types: b, b, as, s, s, s, t, t. All <purple>readonly</purple>, every last one. โญ
๐ The watchdog control panel
Now the fun part โ six properties that are readwrite and Privileged("true"), all with EmitsChangedSignal("false"):
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite t RuntimeWatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite t RuntimeWatchdogPreUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite s RuntimeWatchdogPreGovernor = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite t RebootWatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite t KExecWatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
@org.freedesktop.systemd1.Privileged("true")
readwrite b ServiceWatchdogs = ...;
Two ts (RuntimeWatchdogUSec, RuntimeWatchdogPreUSec), then the one s in the group (RuntimeWatchdogPreGovernor โ the only string here, main character behaviour honestly), then two more ts (RebootWatchdogUSec, KExecWatchdogUSec), and it finishes on a b (ServiceWatchdogs). Six for six on readwrite + Privileged("true") + EmitsChangedSignal("false"). ๐
๐ Last two, and they're "false"
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s SystemState = '...';
Two plain readonly strings, both "false", and that closes out the property list. Whew. ๐ฎโ๐จ
And yeah โ the manager object still has more to show you, so don't go anywhere. ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly y ExitCode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultTimerAccuracyUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultTimeoutStartUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultTimeoutStopUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultTimeoutAbortUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultDeviceTimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultRestartUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultStartLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DefaultStartLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t EventLoopRateLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u EventLoopRateLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultIOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultIPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultMemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultTasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitCPU = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitCPUSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitFSIZE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitFSIZESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitDATA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitDATASoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitSTACK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitSTACKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitCORE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitCORESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRSS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRSSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNOFILE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNOFILESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitAS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitASSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNPROC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNPROCSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitMEMLOCK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitMEMLOCKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitLOCKS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitLOCKSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitSIGPENDING = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitSIGPENDINGSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitMSGQUEUE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitMSGQUEUESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNICE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitNICESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRTPRIO = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRTPRIOSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRTTIME = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DefaultLimitRTTIMESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultMemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DefaultMemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultCPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DefaultCPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t DefaultIOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DefaultIOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s DefaultOOMPolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i DefaultOOMScoreAdjust = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultRestrictSUIDSGID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s CtrlAltDelBurstAction = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u SoftRebootsCount = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u KExecCount = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ReloadCount = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultMemoryZSwapWriteback = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
okay so that whole wall right there? that's the rest of the manager's properties ๐ bestie it's giving deep lore, and the very last three lines โ org.freedesktop.DBus.Peer, org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties โ are just the standard D-Bus housekeeping interfaces every object has, and that final }; closes the whole org.freedesktop.systemd1.Manager interface block. slay, we survived the property list ๐ซถ
๐ Methods ๐
okay so before we even start โ there's a lil quirk here that lowkey trips everybody up, so let's get it out of the way:
Note that many of the methods exist twice: once on the Manager object and once on the respective unit objects. This is to optimize access times so that methods that belong to unit objects do not have to be called with a resolved unit path, but can be called with only the unit id, too.
fr fr โ same method, two doors, pick whichever's faster for you ๐ชโจ
GetUnit()โ your โจlookup bestieโจ. You hand it a unit name, it hands you back the unit object path. That's it. But heads up: if a unit hasn't been loaded yet by that name, this method fails. No unit, no path, no mercy ๐GetUnitByPID()โ same energy but for processes. You give it a UNIX PID and it returns the object path of the unit that PID belongs to. The catch? That PID has to refer to an existing system process, so no asking about ghosts ๐ปGetUnitByPIDFD()โ the glow-up version of the above ๐ instead of a PID you query with a Linux PIDFD (see:pidfd_open(2)), which is safer because UNIX PIDs can get recycled โ like, that PID you knew could get reused by a whole different process and then you'd be asking about a stranger ๐ญ This one returns the unit id and the invocation id, together with the unit object path. three for the price of one, we love to see it ๐LoadUnit()โ basicallyGetUnit()'s overachieving sibling. It does the same thing but will load the unit from disk if possible. no vibes left behind ๐ฆStartUnit()โ the main character ๐ It enqueues a start job, and possibly some depending jobs too. Two args: the unit you wanna activate, and a mode string. And that mode has to be exactly one of these five, no improvising:"replace"โ starts the unit and its dependencies, and it may replace already-queued jobs that conflict with it. out with the old ๐"fail"โ starts the unit and its dependencies, but fails if that would change an already queued job. it's giving "i don't do edits" ๐"isolate"โ starts the unit in question and terminates all units that are not dependencies of it. dramatic. iconic. very "you're either with me or you're gone" ๐"ignore-dependencies"โ starts a unit but ignores all its dependencies. bold."ignore-requirements"โ starts a unit but only ignores the requirement dependencies.
Not recommended to make use of the latter two options. fr fr, just don't ๐
And on a successful reply, this method returns the newly created job object that got enqueued for asynchronous activation. So if you actually care about whether the start worked? you can't just vibe and assume ๐ญ you have to track the outcome of that job.
The โจrace-freeโจ way to do it: first subscribe to the JobRemoved() signal, then call StartUnit(), then use the returned job object to filter out all the unrelated JobRemoved() signals until the one you want shows up โ that one carries the result of the start operation. no cap, order matters here, do it in that order or you're gonna have a bad time ๐
StartUnitReplace()โStartUnit()again, but it takes a job that's queued for one unit and replaces it with a job for another unit. swap szn ๐StartUnitWithFlags()โStartUnit()but you can also pass an extraflagsparameter. And bestie, listen: it does not support any flags for now, it's just reserved for future extensions. so don't get excited, there's nothing in there yet, it's a cute empty box ๐StopUnit()โStartUnit()'s opposite-number ๐ it stops the specified unit instead of starting it. oh andโ
Note that the "isolate" mode is invalid for this method. don't try it, it will not go well ๐
and that's the methods so far โ yes there's more coming, don't you dare close the tab yet ๐
ReloadUnit(), RestartUnit(), TryRestartUnit(), ReloadOrRestartUnit(), and ReloadOrTryRestartUnit() are your little glow-up squad for restarting and/or reloading a unit. ๐
They take basically the same args as StartUnit(). Reloading only happens if the unit's already running โ otherwise it just fails, no cap. And if you restart a service that isn't running? It gets started, unless you went with the "Try" flavor, in which case a not-running service is left completely alone by the restart. The "ReloadOrRestart" flavors are the flexible besties: they try a reload if the unit can do it, and fall back to a full restart otherwise. ๐
EnqueueUnitJob() is giving the same energy as all those StartUnit()/StopUnit()/RestartUnit() methods up above, but it's the unified interface that works on one single unit. The job_type argument picks the job type, and it's one of "start", "stop", "reload", "restart", "try-restart", "reload-or-restart" or "reload-or-try-restart". The job_mode argument matches the mode argument of StartUnit(). On reply, the method hands you back:
- the enqueued anchor job's numeric id and object path,
- the affected unit's id and object path,
- the job type that was actually queued (after type collapsing โ so like,
"reload-or-restart"becomes"restart"or"reload"), and - an array of additional jobs that got enqueued as part of the same transaction, just to satisfy dependencies. ๐ฆ
EnqueueUnitJobMany() is the same vibe as EnqueueUnitJob(), but it handles multiple units at once. All the requested units go into a single transaction, which is honestly necessary to properly honour After=/Before= ordering between units passed in the same call โ no matter what order they're in in the array, periodt. The job_type argument applies to each listed unit, including the magic values "reload-or-restart" and "reload-or-try-restart", which get resolved per unit (units that support reloading get a reload job, everyone else gets a restart). The flags argument doesn't support any flags for now and must be passed as "0" โ it's reserved for future extensions, so don't come for it. On reply, you get an array of tuples describing the anchor job enqueued for each requested unit:
- the numeric job id,
- the job object path,
- the unit id,
- the unit object path, and
- the job type that was actually queued.
heads up bestie โ the order of tuples in the reply is unspecified and may not match the order of your input array. ๐
EnqueueMarkedJobs() creates reload/restart jobs for units that have been appropriately marked โ see the Markers property above. It's equivalent to calling TryRestartUnit() or ReloadOrTryRestartUnit() for the marked units. โจ
BindMountUnit() lets you bind mount new files or directories into a running service's mount namespace. If the kernel supports it, any prior mount on the selected target gets replaced by the new mount. If not supported, the prior mount just gets over-mounted instead โ but it stays pinned and inaccessible. ๐ญ
MountImageUnit() does the same thing but for mounting new images into a running service's mount namespace. Same deal: if the kernel's got your back, the prior mount on the selected target is replaced. If not, the prior mount is over-mounted but stays pinned and inaccessible. ๐ธ
KillUnit() is how you kill (i.e. send a signal to) all the processes of a unit. It takes the unit name, an enum who, and a UNIX signal number to send. The who enum is one of "main", "control", "cgroup" or "all":
"main"โ only the main process of the unit gets killed."control"โ only the control process of the unit gets killed."cgroup"โ only the processes in the control group of the unit get killed, which might or might not include the main and control processes too."all"โ literally everything dies: the main process, the control process, and those in the control group. ๐
A "control" process is, for example, a process configured via ExecStop= that gets spawned in parallel to the main daemon process to shut it down. The value can be suffixed by -fail, in which case the operation will fail if no matching process was found (otherwise it returns successfully while executing absolutely no operation, iconic).
KillUnitSubgroup() is just like KillUnit() but takes an additional path argument that selects a sub-control group of the unit's control group. Only processes in that subgroup get killed. The path may be specified with or without a leading "/" โ either way it's taken relative to the unit's control group. If the subgroup path is specified as an empty string or as "/", it has the same effect as KillUnit(). If it's anything else, the whom parameter must be set to either "cgroup" or "cgroup-fail". ๐
QueueSignalUnit() is similar to KillUnit() but it may be used to enqueue a POSIX Realtime Signal (i.e. SIGRTMIN+... and SIGRTMAX-...) to the selected process(es). It takes the same parameters as KillUnit() with one extra argument: an integer that gets passed in the sival_int value accompanying the queued signal. See sigqueue(3) for details. ๐ซถ
GetJob() returns the job object path for a specific job, identified by its id.
CancelJob() cancels a specific job identified by its numeric ID. This operation is also available as the Cancel() method of Job objects (see below), and it exists primarily to reduce the necessary round trips to execute this operation. Note that this won't have any effect on jobs whose execution has already begun. ๐
ClearJobs() flushes the job queue, removing all jobs that are still queued. Note that this does not have any effect on jobs whose execution has already begun โ it only flushes jobs that are queued and haven't yet started executing.
ResetFailedUnit() resets the "failed" state of a specific unit. Fresh start energy. โจ
SetShowStatus() configures the display of status messages during bootup and shutdown. The mode parameter can be set to any value that's valid for the systemd.show_status kernel parameter. For more info about systemd.show_status, see systemd(1). The mode parameter can also be set to an empty string โ when mode is an empty string, SetShowStatus() resets ShowStatus back to its original value. You can use SetShowStatus() to create a service that does something like this:
- Send a D-Bus message that will turn off status messages.
- Block until a reply to that message is received.
- Print multiple lines without being interrupted by status messages.
- Send a D-Bus message that will reset
ShowStatusback to its original value.
ResetFailed() resets the "failed" state of all units. Clean slate, we love to see it. ๐
ListUnits() returns an array of all currently loaded units. Note that units may be known by multiple names at the same time, so there might be more unit names loaded than actual units behind them. The array consists of structures with the following elements:
- The primary unit name as string
- The human-readable description string
- The load state (i.e. whether the unit file has been loaded successfully)
- The active state (i.e. whether the unit is currently started or not)
- The sub state (a more fine-grained version of the active state that is specific to the unit type, which the active state is not)
- A unit that is being followed in its state by this unit, if there is any, otherwise the empty string.
- The unit object path
- If there is a job queued for the job unit, the numeric job id,
0otherwise - The job type as string
- The job object path
ListJobs() returns an array with all currently queued jobs. Returns an array consisting of structures with the following elements:
- The numeric job id
- The primary unit name for this job
- The job type as string
- The job state as string
- The job object path
- The unit object path
Subscribe() enables most bus signals to be sent out. Clients that are interested in signals need to call this method. Signals are only sent out if at least one client invoked this method. Note that this behavior applies to all the signals that the object in /org/freedesktop/systemd1 may emit โ including the D-Bus standard org.freedesktop.DBus.Properties.PropertiesChanged signal and others that don't belong to the org.freedesktop.systemd1 interface. ๐ฆ
Unsubscribe() reverts the signal subscription that Subscribe() implements. It's not necessary to invoke Unsubscribe(), since clients are tracked โ signals stop being sent out as soon as all clients that previously asked for Subscribe() either closed their connection to the bus or invoked Unsubscribe(). ๐
Dump() returns a text dump of the internal service manager state. This is a privileged, low-level debugging interface only. The returned string is supposed to be readable exclusively by developers, and not programmatically. There's no interface stability guaranteed on the returned string โ new fields may be added any time, old fields removed, and the general structure may be rearranged drastically between releases. This is exposed by systemd-analyze(1)'s dump command. Similarly, DumpUnitsMatchingPatterns() returns the internal state of units whose names match the glob expressions specified in the patterns argument. The DumpByFileDescriptor()/DumpUnitsMatchingPatternsByFileDescriptor() methods are identical to Dump()/DumpUnitsMatchingPatterns(), but return data serialized into a file descriptor (the client should read the text data from it until hitting EOF). Given the size limits on D-Bus messages and the possibly large size of the returned strings, DumpByFileDescriptor()/DumpUnitsMatchingPatternsByFileDescriptor() are usually the preferred interface, since it ensures the data can be passed reliably from the service manager to the client. Note though that they cannot work when communicating with the service manager remotely, as file descriptors are strictly local to a system. All the Dump*() methods are rate limited for unprivileged users. ๐ค
Reload() may be invoked to reload all unit files. ๐ธ
Reexecute() may be invoked to reexecute the main manager process. It will serialize its state, reexecute, and deserialize the state again. This is useful for upgrades and is a more comprehensive version of Reload(). ๐ฅ
Exit() may be invoked to ask the manager to exit. This is not available for the system manager and is useful only for user session managers. ๐
Reboot(), PowerOff(), Halt(), KExec() and SoftReboot() are the "okay we're DONE here" buttons โ they ask for an immediate reboot, power down, halt, kexec-based reboot, or soft reboot of the system. Bestie, listen: this does not shut down any services. It just immediately transitions into the later shutdown operation. ๐ These functions are normally only called as the very last step of shutdown, so pls do not call them directly, okay? If you actually wanna shut the machine down, the better move is to invoke Reboot(), RebootWithFlags() or PowerOff() on the systemd-logind manager object โ check org.freedesktop.login1(5) for the deets. ๐ซถ
SoftReboot() takes an argument for the path of the root file system to activate for the next boot cycle. If you pass an empty string, the /run/nextroot/ path gets used โ but only if it exists. ๐
SwitchRoot() is for transitioning to a new root directory. It's meant for use in the initrd, and also for going from the host system into a shutdown initrd. It takes two arguments: the new root directory (which you have to specify) and an init binary path (which you can leave empty โ in that case it gets automatically searched for). The state of the system manager gets serialized before the transition, and after it, the manager binary on the main system is invoked and replaces the old PID 1. Then all that state gets deserialized. โจ
SetEnvironment() lets you alter the environment block that's passed to every spawned process. It takes a string array of environment variable assignments, and any previously set env vars get overridden. simple as that. ๐
UnsetEnvironment() does the opposite โ it unsets env vars. It takes a string array of environment variable names. Every variable you list gets unset (if it was set before) and is no longer passed to spawned processes. If a variable wasn't set in the first place, this method just... has no effect. It won't fail on you though. no drama. ๐
UnsetAndSetEnvironment() is literally UnsetEnvironment() + SetEnvironment() combined, the way that it takes two lists. First list = variables to unset. Second list = assignments to set. And if a variable shows up in both lists? It's set when the method returns โ so the set list overrides the unset list. periodt. ๐ฅ
ListUnitFiles() returns an array of unit names plus their enablement status. Quick vibe check on the difference: ListUnit() returns units currently loaded into memory, while ListUnitFiles() returns unit files found on disk. And ngl, while most units are read directly from a unit file with the same name, some units aren't backed by files at all, and some files (templates) can't be loaded directly as units โ they have to be instantiated instead. ๐ฆ
GetUnitFileState() returns the current enablement status of one specific unit file.
EnableUnitFiles() enables one or more units in the system (by creating symlinks to them in /etc/ or /run/). It takes a list of unit files to enable โ either just file names, or full absolute paths if the unit files live outside the usual unit search paths โ plus two booleans:
- the first controls whether the unit is enabled for runtime only (
true,/run/) or persistently (false,/etc/) - the second controls whether symlinks pointing to other units shall be replaced if necessary
This method returns one boolean and an array of the changes made. The boolean signals whether the unit files contained any enablement information (i.e. an [Install] section). The changes array consists of structures with three strings: the type of the change (one of "symlink" or "unlink"), the file name of the symlink, and the destination of the symlink. Heads up: most of the calls below return a changes list in this same format. ๐
Similarly, DisableUnitFiles() disables one or more units in the system โ i.e. it removes all symlinks to them in /etc/ and /run/.
The EnableUnitFilesWithFlags() and DisableUnitFilesWithFlags() calls take options as flags instead of booleans, so things stay extendable. Here's how they're defined:
#define SD_SYSTEMD_UNIT_RUNTIME (UINT64_C(1) << 0)
#define SD_SYSTEMD_UNIT_FORCE (UINT64_C(1) << 1)
#define SD_SYSTEMD_UNIT_PORTABLE (UINT64_C(1) << 2)
SD_SYSTEMD_UNIT_RUNTIMEโ enable or disable the unit for runtime onlySD_SYSTEMD_UNIT_FORCEโ controls whether symlinks pointing to other units shall be replaced if necessarySD_SYSTEMD_UNIT_PORTABLEโ adds or removes the symlinks in/etc/systemd/system.attachedand/run/systemd/system.attached
DisableUnitFilesWithFlagsAndInstallInfo() is similar to DisableUnitFilesWithFlags() and takes the same arguments โ but it also returns a boolean indicating whether the unit files contain any enablement information, just like EnableUnitFiles(). The changes made are still returned in an array. ๐
Similarly, ReenableUnitFiles() applies the changes to one or more units that would result from disabling and enabling the unit quickly one after the other, in an atomic fashion. This is useful for applying updated [Install] information contained in unit files. โจ
Similarly, LinkUnitFiles() links unit files (ones located outside of the usual unit search paths) into the unit search path.
Similarly, PresetUnitFiles() enables/disables one or more unit files according to the preset policy. See systemd.preset(5) for more info. ๐ธ
Similarly, MaskUnitFiles() masks unit files, and UnmaskUnitFiles() unmasks them again. the cycle of life fr fr. ๐
SetDefaultTarget() changes the default.target link. See bootup(7) for more.
GetDefaultTarget() retrieves the name of the unit to which default.target is aliased.
SetUnitProperties() can modify certain unit properties at runtime. Not all properties can be changed at runtime, but a lot of resource management settings can (primarily those listed in systemd.resource-control(5)). The changes apply instantly and get stored on disk for future boots โ unless runtime is true, in which case the settings only apply until the next reboot. name is the name of the unit to modify. properties are the settings to set, encoded as an array of property name and value pairs. Note that this is not a dictionary! And also note: when setting array properties with this method, it usually results in appending to the pre-configured array. To reset configured arrays, set the property to an empty array first, then append to it. iykyk. ๐
StartTransientUnit() creates and starts a transient unit โ one that gets released as soon as it's not running or referenced anymore, or the system is rebooted. name is the unit name including its suffix, and it must be unique. mode is the same as in StartUnit(). properties contains properties of the unit, specified like in SetUnitProperties(). aux is currently unused and should be passed as an empty array. See the New Control Group Interface[2] for more info on how to use this for resource control purposes. ๐
DumpUnitFileDescriptorStore() returns an array with information about the file descriptors currently in the file descriptor store of the specified unit. This call is equivalent to DumpFileDescriptorStore() on the org.freedesktop.systemd1.Service. For further details, see below. ๐
CleanUnit() deletes the configuration, state, logs, cache and runtime data directories, and clears out the file descriptor store for the unit โ as specified in the mask parameters. The possible values are "configuration", "state", "logs", "cache", "runtime", "fdstore", and "all". ๐งนโจ
RemoveSubgroupFromUnit() removes a subcgroup belonging to a unit's cgroup. It takes three arguments: the unit name (if empty, defaults to the caller's unit), a cgroup path (which must start with a slash /), taken relative to the unit's cgroup, and a flags argument (which must be zero for now). This is primarily useful for unprivileged service managers to ask the system service manager to remove subcgroups it manages โ in case one was delegated to other UIDs. ๐
๐ซ Signals ๐ซ
okay so, quick note bestie: most signals are sent out only after Subscribe() has been invoked by at least one client. Make sure you invoke this method when you're subscribing to these signals! ๐
UnitNew() and UnitRemoved() get sent out each time a new unit is loaded or unloaded. This has little to do with whether a unit is available on disk or not โ it simply reflects the units currently loaded into memory. These signals take two parameters: the primary unit name and the object path. ๐ฆ
JobNew() and JobRemoved() get sent out each time a new job is queued or dequeued. Both signals take the numeric job ID, the bus path, and the primary unit name for this job as arguments. JobRemoved() also includes a result string, which is one of:
"done"โ successful execution of a job"canceled"โ the job was canceled (viaCancelJob()above) before it finished execution. Note that this does not necessarily mean the job operation is actually cancelled too โ see above."timeout"โ the job timeout was reached"failed"โ the job failed"dependency"โ a job this job depended on failed, and the job hence was removed as well"skipped"โ a job was skipped because it did not apply to the unit's current state
StartupFinished() is sent out when startup finishes. It carries six microsecond timespan values, each indicating how much boot time was spent in the firmware (if known), in the boot loader (if known), in the kernel initialization phase, in the initrd (if known), in userspace, and in total. These values may also be calculated from the FirmwareTimestampMonotonic, LoaderTimestampMonotonic, InitRDTimestampMonotonic, UserspaceTimestampMonotonic, and FinishTimestampMonotonic properties (see below). โฑ๏ธ
UnitFilesChanged() is sent out each time the list of enabled or masked unit files on disk has changed.
Reloading() is sent out immediately before a daemon reload is done (with the boolean parameter set to True) and after a daemon reload is completed (with the boolean parameter set to False). UIs can use this to optimize UI updates. ๐
๐ Properties ๐
Most properties simply reflect the respective options in /etc/systemd/system.conf and the kernel command line. cute, right?
The others:
Version encodes the version string of the running systemd instance. Note that the version string is purely informational. It should not be parsed, and one may not assume the version to be formatted in any particular way. We take the liberty to change the versioning scheme at any time, and it is not part of the public API. ๐
Features encodes the features that have been enabled and disabled for this build. Enabled options are prefixed with +, disabled options with -.
"unmerged-usr"โ /bin, /sbin and /lib* are not symlinks to their counterparts under /usr/. ๐ bestie if you wanna know more about this whole saga, go consult The Case for the /usr Merge[3].
Added in version 252.
"unmerged-bin"โ /usr/sbin is not a symlink to /usr/bin/. ๐ญ
Added in version 256.
"var-run-bad"โ either /run/ doesn't exist, or /var/run is not a symlink pointing at /run/. ๐
Added in version 252.
"cgroupsv1"โ the system is running on the deprecated cgroup v1 hierarchy. yes this is a callout, no it's not a vibe.
Added in version 252.
"local-hwclock"โ the local hardware clock (RTC) is configured to be in local time instead of UTC. โฐ
Added in version 252.
"support-ended"โ the system is running past the end of support that the vendor declared. Go read the description ofSUPPORT_END=inos-release(5)for the tea. ๐ซ
Added in version 252.
"old-kernel"โ the system is running a kernel version that is older than the minimum supported by this version of systemd. โจ
Added in version 252.
"overflowuid-not-65534","overflowgid-not-65534"โ the kernel overflow UID or GID has a value that is not65534. ๐
Added in version 252.
"short-uid-range","short-gid-range"โ the UID or GID range assigned to the running systemd instance covers less than0...65534. ๐
Added in version 252.
FirmwareTimestamp, FirmwareTimestampMonotonic, LoaderTimestamp, LoaderTimestampMonotonic, KernelTimestamp, KernelTimestampMonotonic, InitRDTimestamp, InitRDTimestampMonotonic, UserspaceTimestamp, UserspaceTimestampMonotonic, FinishTimestamp, FinishTimestampMonotonic, ShutdownStartTimestamp and ShutdownStartTimestampMonotonic encode CLOCK_REALTIME and CLOCK_MONOTONIC microsecond timestamps, taken when:
- the firmware first began execution,
- the boot loader first began execution,
- the kernel first began execution,
- the initrd first began execution,
- the main systemd instance began execution,
- all queued startup jobs finished execution,
- and finally, when a shutdown operation first began execution. ๐
These values are so useful for figuring out boot-time performance, fr fr. Just note that because monotonic time starts with kernel startup, the KernelTimestampMonotonic timestamp will always be 0, and FirmwareTimestampMonotonic and LoaderTimestampMonotonic are meant to be read as negative values. Also, not all fields are always available โ it depends on the firmware, boot loader or initrd implementation being used. In those cases the respective pairs of timestamps are both 0, which is the polite way of saying "no data available bestie". ๐ญ
ShutdownFinishTimestamp and ShutdownFinishTimestampMonotonic encode CLOCK_REALTIME and CLOCK_MONOTONIC microsecond timestamps taken when all units have finished stopping during shutdown, i.e. when shutdown.target is reached. Together with ShutdownStartTimestamp (which is taken when unit stopping begins) they bracket the time spent stopping units. ๐ฆ
PreviousShutdownStartTimestamp, PreviousShutdownFinishTimestamp, PreviousShutdownLateStartTimestamp, PreviousShutdownLateFinishTimestamp and their Monotonic counterparts encode CLOCK_REALTIME and CLOCK_MONOTONIC microsecond timestamps describing the shutdown of the previous boot, restored from the Live Update Orchestrator (LUO) payload after a kexec-based live update. PreviousShutdownStartTimestamp and PreviousShutdownFinishTimestamp bracket the unit-stopping phase of that previous boot, while PreviousShutdownLateStartTimestamp and PreviousShutdownLateFinishTimestamp are taken by systemd-shutdown itself โ when it began execution, and when it was about to kexec() into the current kernel, respectively. Unlike the current cycle's ShutdownStartTimestamp and ShutdownFinishTimestamp (which describe an in-progress shutdown of the running system), these always refer to a previous, already-completed boot, similar to the firmware, boot loader and kernel timestamps. They're populated only after a kexec-based live update, and they're useful for determining shutdown and live-update performance; otherwise they are all 0. ๐
UnitsLoadTimestamp and UnitsLoadTimestampMonotonic encode CLOCK_REALTIME and CLOCK_MONOTONIC microseconds timestamps (as described above). The timestamps are taken every time when the manager starts loading unit files. โญ
Similarly, the SecurityStartTimestamp, GeneratorsStartTimestamp and LoadUnitTimestamp (as well as their monotonic and stop counterparts) expose performance data for uploading the security policies to the kernel (such as the SELinux, IMA, or SMACK policies), for running the generator tools, and for loading the unit files. ๐
NNames encodes how many unit names are currently known. This only includes names of units that are currently loaded, and it can be more than the amount of actually loaded units, since units may have more than one name. ๐คฏ
NJobs encodes how many jobs are currently queued. ๐
NInstalledJobs encodes how many jobs have ever been queued in total. ๐ข
NFailedJobs encodes how many jobs have ever failed in total. ๐ฌ
TransactionsWithOrderingCycle encodes IDs of transactions that encountered an ordering cycle. ๐
Progress encodes boot progress as a floating point value between 0.0 and 1.0. This value begins at 0.0 at early-boot and ends at 1.0 when boot is finished, and it's based on the number of executed and queued jobs. After startup, this field is always 1.0, indicating a finished boot. ๐
Environment encodes the environment block passed to all executed services. It may be altered with bus calls such as SetEnvironment() (see above). ๐ธ
ShowStatus encodes systemd's current policy for displaying status messages during bootup and shutdown. Its value can be any valid value for the systemd.show_status kernel parameter (see systemd(1)). It may be altered using SetShowStatus() (see above). ๐
UnitPath encodes the currently active unit file search path. It's an array of file system paths encoded as strings. ๐๏ธ
SoftRebootsCount encodes how many soft-reboots were successfully completed since the last full boot. Starts at "0". ๐
KExecCount encodes how many kexec-based live updates were successfully completed since the last full boot. Starts at "0". The counter is preserved across the kexec through the Live Update Orchestrator (LUO), and is hence "0" when the kernel does not provide LUO support. ๐
ReloadCount encodes the number of successfully completed configuration reloads of the manager. The counter is reset to "0" on daemon-reexec and on the initial boot. โป๏ธ
Virtualization contains a short ID string describing the virtualization technology the system runs in. On bare-metal hardware this is the empty string. Otherwise it contains an identifier such as "kvm", "vmware" and so on. For a full list of IDs see systemd-detect-virt(1). Note that only the innermost virtualization technology is exported here. This detects both full-machine virtualizations (VMs) and shared-kernel virtualization (containers). ๐ฅ๏ธ
ConfidentialVirtualization contains a short ID string describing the confidential virtualization technology the system runs in. On bare-metal hardware this is the empty string. Otherwise it contains an identifier such as "sev", "sev-es", "sev-snp", "tdx" and so on. For a full list of IDs see systemd-detect-virt(1) . ๐
Architecture contains a short ID string describing the architecture the systemd instance is running on. This follows the same vocabulary as ConditionArchitectures=. ๐ง
ControlGroup contains the root control group path of this system manager. Note that the root path is encoded as the empty string here (not as "/"!), so that it can be appended to /sys/fs/cgroup/systemd easily. This value will be set to the empty string for the host instance and some other string for container instances. ๐ซถ
AccessSELinuxContext contains the SELinux context that is used to control access to the unit. It's read from the unit file when it is loaded, and cached until the service manager is reloaded. This property contains an empty string if SELinux is not used, or if no label could be read (for example because the unit is not backed by a file on disk). ๐ท๏ธ
SystemState contains the current state of the system manager. The possible values are:
"initializing"โ the system is booting, andbasic.targethas not been reached yet. ๐ฑ"starting"โ the system is booting, andbasic.targethas been reached. โจ"running"โ the system has finished booting, and no units are in the failed state. ๐"degraded"โ the system has finished booting, but some units are in the failed state. ๐ญ"maintenance"โ the system has finished booting, but it has been put in rescue or maintenance mode. ๐ ๏ธ"stopping"โ the system is shutting down. ๐ค
๐ Security ๐
Read access is generally granted to all clients. ๐ซถ Additionally, for unprivileged clients, some operations are allowed through the polkit privilege system. Here's the whole vibe check, bestie:
- Operations which modify unit state โ
StartUnit(),StopUnit(),KillUnit(),KillUnitSubgroup(),QueueSignalUnit(),RestartUnit()and similar, plusSetUnitProperties()โ requireorg.freedesktop.systemd1.manage-units. ๐ฅ - Operations which modify unit file enablement state โ
EnableUnitFiles(),DisableUnitFiles(),EnableUnitFilesWithFlags(),DisableUnitFilesWithFlags(),ReenableUnitFiles(),LinkUnitFiles(),PresetUnitFiles(),MaskUnitFiles(), and similar โ requireorg.freedesktop.systemd1.manage-unit-files. ๐ - Operations which modify the exported environment โ
SetEnvironment(),UnsetEnvironment(),UnsetAndSetEnvironment()โ requireorg.freedesktop.systemd1.set-environment. ๐ Reload()andReexecute()requireorg.freedesktop.systemd1.reload-daemon. ๐- Operations which dump internal state require
org.freedesktop.systemd1.bypass-dump-ratelimitto avoid rate limits. ๐ฆ
ngl if you're hitting the polkit wall and wondering why your call got denied โ it's probably one of these. iykyk ๐
๐ฆ UNIT OBJECTS ๐ฆ
okay so now we get to the actual units, bestie. like every single unit on your system gets its own little D-Bus node, and here's what one of them looks like. the example systemd ships is avahi_2ddaemon_2eservice, which is avahi-daemon.service with the escaping applied (- becomes _2d, . becomes _2e โ that's just how D-Bus path names roll, iykyk ๐
).
so the node path is:
node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
interface org.freedesktop.systemd1.Unit {
methods:
Start(in s mode,
out o job);
Stop(in s mode,
out o job);
Reload(in s mode,
out o job);
Restart(in s mode,
out o job);
TryRestart(in s mode,
out o job);
ReloadOrRestart(in s mode,
out o job);
ReloadOrTryRestart(in s mode,
out o job);
EnqueueJob(in s job_type,
in s job_mode,
out u job_id,
out o job_path,
out s unit_id,
out o unit_path,
out s job_type,
out a(uosos) affected_jobs);
Kill(in s whom,
in i signal);
KillSubgroup(in s subgroup,
in i signal);
QueueSignal(in s whom,
in i signal,
in i value);
ResetFailed();
SetProperties(in b runtime,
in a(sv) properties);
Ref();
Unref();
Clean(in as mask);
Freeze();
Thaw();
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Id = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Names = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Following = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Requires = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Requisite = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Wants = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as BindsTo = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PartOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Upholds = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RequiredBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RequisiteOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as WantedBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as BoundBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UpheldBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConsistsOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Conflicts = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConflictedBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Before = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as After = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as OnSuccess = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as OnSuccessOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as OnFailure = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as OnFailureOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Triggers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as TriggeredBy = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PropagatesReloadTo = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReloadPropagatedFrom = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PropagatesStopTo = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StopPropagatedFrom = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as JoinsNamespaceOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SliceOf = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RequiresMountsFor = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as WantsMountsFor = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Documentation = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Description = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s AccessSELinuxContext = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s LoadState = '...';
readonly s ActiveState = '...';
readonly s FreezerState = '...';
readonly s SubState = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s FragmentPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SourcePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as DropInPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s UnitFileState = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s UnitFilePreset = '...';
readonly t StateChangeTimestamp = ...;
readonly t StateChangeTimestampMonotonic = ...;
readonly t InactiveExitTimestamp = ...;
readonly t InactiveExitTimestampMonotonic = ...;
readonly t ActiveEnterTimestamp = ...;
readonly t ActiveEnterTimestampMonotonic = ...;
readonly t ActiveExitTimestamp = ...;
readonly t ActiveExitTimestampMonotonic = ...;
readonly t InactiveEnterTimestamp = ...;
readonly t InactiveEnterTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanStart = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanStop = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanReload = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanIsolate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CanClean = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanFreeze = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CanLiveMount = ...;
readonly (uo) Job = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StopWhenUnneeded = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RefuseManualStart = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RefuseManualStop = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b AllowIsolate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DefaultDependencies = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SurviveFinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OnSuccessJobMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OnFailureJobMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreOnIsolate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b NeedDaemonReload = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as Markers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t JobTimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t JobRunningTimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s JobTimeoutAction = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s JobTimeoutRebootArgument = '...';
readonly b ConditionResult = ...;
readonly b AssertResult = ...;
readonly t ConditionTimestamp = ...;
readonly t ConditionTimestampMonotonic = ...;
readonly t AssertTimestamp = ...;
readonly t AssertTimestampMonotonic = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sbbsi) Conditions = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sbbsi) Asserts = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (ss) LoadError = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Transient = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Perpetual = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t StartLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StartLimitBurst = ...;
๐ซถ the methods, real quick
so the org.freedesktop.systemd1.Unit interface hands you these, in this exact order:
Start(in s mode, out o job)Stop(in s mode, out o job)Reload(in s mode, out o job)Restart(in s mode, out o job)TryRestart(in s mode, out o job)ReloadOrRestart(in s mode, out o job)ReloadOrTryRestart(in s mode, out o job)EnqueueJob(in s job_type, in s job_mode, out u job_id, out o job_path, out s unit_id, out o unit_path, out s job_type, out a(uosos) affected_jobs)Kill(in s whom, in i signal)KillSubgroup(in s subgroup, in i signal)QueueSignal(in s whom, in i signal, in i value)ResetFailed()SetProperties(in b runtime, in a(sv) properties)Ref()Unref()Clean(in as mask)Freeze()Thaw()
notice basically every state-changing one returns an o (object path) called job โ that's your job object, your receipt, your little tracker for "yeah bestie, that's in flight". โจ and EnqueueJob is the extra one that hands you the whole situation: job_id, job_path, unit_id, unit_path, job_type, plus affected_jobs as an array of (uosos) tuples. that's a whole meal. ๐
๐ the properties, all of them
there's like, a lot, so let's vibe through the categories โ every single name stays exactly as-is, no cap:
- identity + naming:
Id,Names,Following,Description,AccessSELinuxContext,Documentation - the dependency web (the way that everything connects to everything ๐ญ):
Requires,Requisite,Wants,BindsTo,PartOf,Upholds,RequiredBy,RequisiteOf,WantedBy,BoundBy,UpheldBy,ConsistsOf,Conflicts,ConflictedBy,Before,After,OnSuccess,OnSuccessOf,OnFailure,OnFailureOf,Triggers,TriggeredBy,PropagatesReloadTo,ReloadPropagatedFrom,PropagatesStopTo,StopPropagatedFrom,JoinsNamespaceOf,SliceOf,RequiresMountsFor,WantsMountsFor - where it lives on disk:
FragmentPath,SourcePath,DropInPaths,UnitFileState,UnitFilePreset - what state it's in rn:
LoadState,ActiveState,FreezerState,SubState,Job - when stuff happened (monotonic twin for each, always):
StateChangeTimestamp,StateChangeTimestampMonotonic,InactiveExitTimestamp,InactiveExitTimestampMonotonic,ActiveEnterTimestamp,ActiveEnterTimestampMonotonic,ActiveExitTimestamp,ActiveExitTimestampMonotonic,InactiveEnterTimestamp,InactiveEnterTimestampMonotonic - permissions / capabilities flags:
CanStart,CanStop,CanReload,CanIsolate,CanClean,CanFreeze,CanLiveMount,StopWhenUnneeded,RefuseManualStart,RefuseManualStop,AllowIsolate,DefaultDependencies,SurviveFinalKillSignal,IgnoreOnIsolate,OnSuccessJobMode,OnFailureJobMode - timeouts + start limiting:
JobTimeoutUSec,JobRunningTimeoutUSec,JobTimeoutAction,JobTimeoutRebootArgument,StartLimitIntervalUSec,StartLimitBurst - conditions & asserts (the "should I even run tho" club):
ConditionResult,AssertResult,ConditionTimestamp,ConditionTimestampMonotonic,AssertTimestamp,AssertTimestampMonotonic,Conditions,Asserts - misc slay:
NeedDaemonReload,Markers,LoadError,Transient,Perpetual
heads up bestie โ the@org.freedesktop.DBus.Property.EmitsChangedSignal(...)line above each property is literally the vibe check on whether D-Bus pings you when it changes."const"= never changes,"false"= changes but no signal,"invalidates"= it'll tell you the whole thing is stale. those annotations are in the code block verbatim, don't skip 'em. ๐
also notice Conditions is typed a(sbbsi) and Asserts is typed a(sbbsi) too, and Job is a (uo) tuple โ u for the id, o for the path. iconic. ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StartLimitAction = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s FailureAction = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FailureActionExitStatus = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SuccessAction = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SuccessActionExitStatus = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RebootArgument = '...';
readonly ay InvocationID = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s CollectMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as Refs = ['...', ...];
readonly a(ss) ActivationDetails = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b DebugInvocation = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
Methods ๐
okay bestie, so Start(), Stop(), Reload(), Restart(), TryRestart(), ReloadOrRestart(), ReloadOrTryRestart(), Kill(), KillSubgroup(), QueueSignal(), ResetFailed(), and SetProperties() do the exact same operation as the respective methods on the Manager object (scroll up, bestie). But these ones operate on the unit object itself, so they don't take a unit name parameter. Invoking the methods directly on the Manager object is a whole vibe because it means you don't need a GetUnit() call to get the unit object for a specific unit name. Calling them on the Manager is therefore a round trip optimization. periodt. ๐
Properties ๐
Idโ contains the primary name of the unit. main character identifier, honestly.Namesโ contains all names of the unit, including the primary name that is also exposed inId. so it's giving full government name plus nicknames.Followingโ either contains the empty string or contains the name of another unit that this unit follows in state. This is used for some device units which reflect the unit state machine of another unit, and which other unit this is might possibly change. lowkey mysterious.Requires,RequiresOverridable,Requisite,RequisiteOverridable,Wants,BindsTo,RequiredBy,RequiredByOverridable,WantedBy,BoundBy,Conflicts,ConflictedBy,Before,After,OnFailure,Triggers,TriggeredBy,PropagatesReloadTo, andRequiresMountsForโ contain arrays which encode the dependencies and their inverse dependencies (where this applies) as configured in the unit file or determined automatically. the friend group drama, but for units.Descriptionโ contains the human-readable description string for the unit. cute little summary.SourcePathโ contains the path to a configuration file this unit is automatically generated from in case it is not a native unit (in which case it contains the empty string). For example, all mount units generated from/etc/fstabhave this field set to/etc/fstab. so it's like the origin story.Documentationโ contains a string array with URLs of documentation for this unit. links to the lore.LoadStateโ contains a state value that reflects whether the configuration file of this unit has been loaded. The following states are currently defined:"loaded","error", and"masked"."loaded"indicates that the configuration was successfully loaded."error"indicates that the configuration failed to load. TheLoadErrorfield (see below) contains information about the cause of this failure."masked"indicates that the unit is currently masked out (i.e. symlinked to/dev/nullor empty). Note that theLoadStateis fully orthogonal to theActiveState(see below) as units without valid loaded configuration might be active (because configuration might have been reloaded at a time where a unit was already active). no cap, they're independent.ActiveStateโ contains a state value that reflects whether the unit is currently active or not. The following states are currently defined:
Table 1. Unit ACTIVE states
activeโ Started, bound, plugged in, ..., depending on the unit type.inactiveโ Stopped, unbound, unplugged, ..., depending on the unit type.failedโ Similar toinactive, but the unit failed in some way (process returned error code on exit, crashed, an operation timed out, or after too many restarts).activatingโ Changing frominactivetoactive.deactivatingโ Changing fromactivetoinactive.maintenanceโ Unit is inactive and a maintenance operation is in progress.reloadingโ Unit is active and it is reloading its configuration.refreshingโ Unit is active and a new mount is being activated in its namespace.
SubStateโ encodes states of the same state machine thatActiveStatecovers, but knows more fine-grained states that are unit-type-specific. WhereActiveStateonly covers eight high-level states,SubStatecovers possibly many more low-level unit-type-specific states that are mapped to the eight high-level states. Note that multiple low-level states might map to the same high-level state, but not vice versa. Not all high-level states have low-level counterparts on all unit types. At this point the low-level states are not documented here, and are more likely to be extended later on than the common high-level states explained above. so it's the director's cut.FragmentPathโ contains the unit file path this unit was read from, if there is one (if not, it contains the empty string). where it lives.UnitFileStateโ encodes the install state of the unit file ofFragmentPath. It currently knows the following states:"enabled","enabled-runtime","linked","linked-runtime","masked","masked-runtime","static","disabled", and"invalid"."enabled"indicates that a unit file is permanently enabled."enable-runtime"indicates the unit file is only temporarily enabled and will no longer be enabled after a reboot (that means, it is enabled via/run/symlinks, rather than/etc/)."linked"indicates that a unit is linked into/etc/permanently."linked-runtime"indicates that a unit is linked into/run/temporarily (until the next reboot)."masked"indicates that the unit file is masked permanently."masked-runtime"indicates that it is masked in/run/temporarily (until the next reboot)."static"indicates that the unit is statically enabled, i.e. always enabled and does not need to be enabled explicitly."invalid"indicates that it could not be determined whether the unit file is enabled. (yes, the list says"enabled-runtime"and the description says"enable-runtime"โ we don't make the rules, we just report them ๐)InactiveExitTimestamp,InactiveExitTimestampMonotonic,ActiveEnterTimestamp,ActiveEnterTimestampMonotonic,ActiveExitTimestamp,ActiveExitTimestampMonotonic,InactiveEnterTimestamp, andInactiveEnterTimestampMonotonicโ containCLOCK_REALTIMEandCLOCK_MONOTONIC64-bit microsecond timestamps of the last time a unit left the inactive state, entered the active state, exited the active state, or entered an inactive state. These are the points in time where the unit transitioned"inactive"/"failed"โ"activating","activating"โ"active","active"โ"deactivating", and finally"deactivating"โ"inactive"/"failed". The fields are 0 in case such a transition has not yet been recorded on this boot. timestamp receipts.CanStart,CanStop, andCanReloadโ encode as booleans whether the unit supports the start, stop or reload operations. Even if a unit supports such an operation, the client might not have the necessary privileges to execute them. so capability โ permission, bestie.CanIsolateโ encodes as a boolean whether the unit may be started in isolation mode.Jobโ encodes the job ID and job object path of the job currently scheduled or executed for this unit, if there is any. If no job is scheduled or executed, the job id field will be 0. no job, no id.StopWhenUnneeded,RefuseManualStart,RefuseManualStop,AllowIsolate,DefaultDependencies,OnFailureIsolate,IgnoreOnIsolate,IgnoreOnSnapshotโ map directly to the corresponding configuration booleans in the unit file. straight up copy-paste from config.NeedDaemonReloadโ is a boolean that indicates whether the configuration file this unit is loaded from (i.e.FragmentPathorSourcePath) has changed since the configuration was read and hence whether a configuration reload is recommended. so if this is true, maybe go reload, bestie.Markersโ an array of string flags, settable withSetUnitProperties(), that's basically your unit waving a lil hand going "hey bestie i need a reload / restart ๐ฅบ". The currently known values are"needs-restart","needs-stop","needs-start"and"needs-reload". Package scripts can use the first three to mark units for a later restart, start, or stop when a new version of the package gets installed or yeeted out. Configuration management scripts can use the fourth to mark units for a later reload when the config gets tweaked. Those flags are not set by the manager itself โ the manager only ever unsets them, and only when it's appropriate, i.e. when the unit is stopped, restarted, or reloaded. When markers are set, they get normalized according to these precedence rules, which are modeled after the job type merging logic. And when new markers are applied incrementally (with the"+"prefix), conflicting existing markers get cleared before the new ones merge in:"needs-reload"loses against literally everything else. If any of"needs-restart","needs-start", or"needs-stop"is set,"needs-reload"gets cleared. ๐"needs-stop"wins against"needs-restart"and"needs-reload", clearing both of them."needs-start"wins against"needs-stop", clearing it."needs-restart"wins against"needs-start". If both are set,"needs-start"gets cleared.
So for example, if a unit currently has "needs-stop" set and a new "+needs-start" marker gets applied, the existing "needs-stop" is cleared and only "needs-start" remains. Conversely, applying "+needs-stop" to any existing marker will clear all other markers โ because "needs-stop" takes precedence over "needs-restart" and "needs-reload", and the new marker clears conflicting existing ones. It's giving "there can only be one" ๐.
JobTimeoutUSecโ maps directly to the corresponding configuration setting in the unit file. no cap, no middleman โจConditionTimestampandConditionTimestampMonotonicโ hold theCLOCK_REALTIME/CLOCK_MONOTONICmicrosecond timestamps of the last time the configured conditions of the unit were checked, or0if they've literally never been checked. Conditions get checked when a unit is requested to start.ConditionResultโ the condition result from the last time the configured conditions of this unit were checked.Conditionsโ all the configured conditions of the unit. For each condition, five fields are given: the condition type (e.g.ConditionPathExists), whether the condition is a trigger condition, whether the condition is reversed, the right hand side of the condition (e.g. the path in the case ofConditionPathExists), and the status. The status can be0, in which case the condition hasn't been checked yet; a positive value, in which case the condition passed; or a negative value, in which case the condition is not met. Currently only0,+1, and-1are used, but additional values may show up in the future โ they'll keep the whole zero/positive/negative meaning though, so don't panic ๐ซถ.LoadErrorโ a pair of strings. If the unit failed to load (as encoded inLoadState, see above), this will include a D-Bus error pair: the error ID plus an explanatory human-readable string of what happened. If it loaded successfully, it's a pair of empty strings. no drama ๐Transientโ a boolean that tells you whether the unit was created as a transient unit (i.e. viaStartTransientUnit()on the manager object).ActivationDetailsโ a list of string pairs, key and value, describing the event that caused the unit to be activated, if any. The key describes the information (e.g.:trigger_unit, with valuefoo.service). This is only filled in if the unit was triggered by a Path or Timer unit, and it's only provided in a best-effort fashion: it's not guaranteed to be set, and it's not guaranteed to be the only trigger. The only thing guaranteed is that it's a valid trigger that caused the activation job to be enqueued and complete successfully. The key value pairs correspond (in lowercase) to the environment variables described in the "Environment Variables Set or Propagated by the Service Manager" section insystemd.exec(5). Heads up bestie: new key value pairs may be added at any time in future versions โ but existing entries will not be removed, promise ๐ค.DebugInvocationโ a boolean that flips totruewhen the unit is restarted with the log level set to debug due to an earlier failure, and flips back tofalsewhen either the unit successfully starts or the restart rate limit is reached. See the"RestartMode="section insystemd.service(5)for more details. she's dramatic but she's consistent ๐OOMKillsโ holds a different value depending on whetherOOMPolicy=killis enabled for the unit or not. If it's enabled, the property contains the number of times the kernel OOM killer killed all the processes in the unit's cgroup and its descendant cgroups. If it's disabled, the property contains the number of processes the kernel OOM killer has killed in the unit's cgroup and its descendant cgroups. And when the corresponding cgroups haven't been realized, it reports18446744073709551615(2^64 - 1) โ yeah, that's the big scary number, that's on purpose ๐ญ.ManagedOOMKillsโ the number of timessystemd-oomdkilled all the processes in the unit's cgroup and its descendant cgroups. When the corresponding cgroups haven't been realized yet, it reports18446744073709551615(2^64 - 1). same energy, different killer ๐ฉธ
๐ Security ๐
Same deal as the methods on the Manager object: read-only access is allowed for everyone. All operations are allowed for clients when the org.freedesktop.systemd1.manage-units privilege is granted by polkit. iykyk ๐
๐ SERVICE UNIT OBJECTS ๐
All service unit objects implement the org.freedesktop.systemd1.Service interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). two interfaces, one unit, main character energy fr fr ๐
okay bestie, we're deep in the introspection dump now โ this is the raw XML that systemd hands you when you ask the bus "so what does this thing even look like?", and we're looking at one specific node. Say hi to:
node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
interface org.freedesktop.systemd1.Service {
methods:
BindMount(in s source,
in s destination,
in b read_only,
in b mkdir);
MountImage(in s source,
in s destination,
in b read_only,
in b mkdir,
in a(ss) options);
DumpFileDescriptorStore(out a(suuutuusu) entries);
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
properties:
no cap, that node name is the escaped/mangled one โ avahi_2ddaemon_2eservice, you know the drill, that's just the unit name wearing a disguise so it can live in a bus path. ๐ And look at those six methods: BindMount(), MountImage(), DumpFileDescriptorStore(), GetProcesses(), AttachProcesses(), RemoveSubgroup(). Six little entry points and every one of them keeps its argument types exactly as written โ in s, in b, in a(ss), out a(suuutuusu), out a(sus), in au, in t. Do not come for the signatures, they are perfect as-is. ๐
then the property parade starts, and the first thing you clock is the annotation sitting on top of basically everything:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Type = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExitType = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Restart = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RestartMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PIDFile = '...';
readonly s NotifyAccess = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestartUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u RestartSteps = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestartMaxDelayUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestartRandomizedDelayUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t RestartUSecNext = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutStartUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutStopUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TimeoutAbortUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TimeoutStartFailureMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TimeoutStopFailureMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeMaxUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeRandomizedExtraUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogTimestamp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t WatchdogTimestampMonotonic = ...;
not me counting the t-typed microsecond properties like it's a hobby. ๐ญ The way that NotifyAccess is sitting there all alone with no annotation above it โ yeah bestie, it's giving "I get to be different", iconic behaviour, we love a main character property. โจ
And the vibe check on the annotations themselves: some get stamped "const", some get stamped "false", and which one you get is literally the โจtellโจ โ just look at the pairs. RestartUSec is const, but its next-door neighbour RestartUSecNext is false. TimeoutStartUSec and TimeoutStopUSec are const, TimeoutAbortUSec is false. WatchdogUSec, WatchdogTimestamp and WatchdogTimestampMonotonic are all false, all three, no crumbs. ๐ฆ
moving on, the booleans and the little status crew arrive:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RootDirectoryStartOnly = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemainAfterExit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b GuessMainPID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (aiai) RestartPreventExitStatus = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (aiai) RestartForceExitStatus = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (aiai) SuccessExitStatus = ...;
readonly u MainPID = ...;
readonly u ControlPID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BusName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u FileDescriptorStoreMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NFileDescriptorStore = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s FileDescriptorStorePreserve = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LUOSession = ['...', ...];
readonly s StatusText = '...';
readonly i StatusErrno = ...;
readonly s StatusBusError = '...';
readonly s StatusVarlinkError = '...';
readonly s Result = '...';
readonly s ReloadResult = '...';
readonly s CleanResult = '...';
readonly s LiveMountResult = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s USBFunctionDescriptors = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s USBFunctionStrings = '...';
readonly u UID = ...;
readonly u GID = ...;
readonly u NRestarts = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OOMPolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) OpenFile = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExtraFileDescriptorNames = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i ReloadSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RefreshOnReload = ['...', ...];
the un-annotated girlies are back: NotifyAccess had company now โ MainPID, ControlPID, StatusText, StatusErrno, StatusBusError, StatusVarlinkError, Result, ReloadResult, CleanResult, LiveMountResult, UID, GID, NRestarts. All just vibing with no EmitsChangedSignal at all. we respect the quiet ones ๐ซถ
Also note the shapes, because they are not all the same and I will not let you pretend they are: (aiai) for RestartPreventExitStatus, RestartForceExitStatus and SuccessExitStatus. as for LUOSession, ExtraFileDescriptorNames and RefreshOnReload โ those show up as ['...', ...]. a(sst) for OpenFile which shows as [...]. i for ReloadSignal, s for the string-y ones, u for MainPID, ControlPID, FileDescriptorStoreMax, NFileDescriptorStore, UID, GID and NRestarts, b for the three booleans. exact types, always. ๐
then the timestamps and the exit bookkeeping, aka the "what even happened" department:
readonly t ExecMainStartTimestamp = ...;
readonly t ExecMainStartTimestampMonotonic = ...;
readonly t ExecMainExitTimestamp = ...;
readonly t ExecMainExitTimestampMonotonic = ...;
readonly t ExecMainHandoffTimestamp = ...;
readonly t ExecMainHandoffTimestampMonotonic = ...;
readonly u ExecMainPID = ...;
readonly i ExecMainCode = ...;
readonly i ExecMainStatus = ...;
start, exit, handoff โ each one twice, once plain and once monotonic, because of course. ๐ And then ExecMainPID (u), ExecMainCode (i), ExecMainStatus (i). no annotation on any of them. they're just out here reporting. ๐
and now the big one, the Exec* families, and heads up because every single one of these carries EmitsChangedSignal("invalidates") โ not const, not false, invalidates:
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecCondition = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecConditionEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStartPre = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecStartPreEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStart = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecStartEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStartPost = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecStartPostEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecReload = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecReloadEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecReloadPost = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecReloadPostEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStop = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecStopEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStopPost = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasasttttuii) ExecStopPostEx = [...];
the way that it's every command slot twice โ the plain flavour a(sasbttttuii) and the Ex flavour a(sasasttttuii) โ for Condition, StartPre, Start, StartPost, Reload, ReloadPost, Stop, StopPost. Sixteen properties. sixteen. ๐ iykyk. and yes, ExecReloadPost and ExecReloadPostEx are really in there, they're not a typo, don't @ me. ๐ง
and then we slide into the runtime/cgroup stats, all of them stamped "false":
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
all the memory โ MemoryCurrent, MemoryPeak, MemorySwapCurrent, MemorySwapPeak, MemoryZSwapCurrent, MemoryAvailable, EffectiveMemoryMax, EffectiveMemoryHigh. the way that ZSwap really said "I'm here too bestie". ๐ญ then CPU: CPUUsageNSec, plus the two ay byte-array ones EffectiveCPUs and EffectiveMemoryNodes showing as [...]. then task counts TasksCurrent and EffectiveTasksMax. then the network four: IPIngressBytes, IPIngressPackets, IPEgressBytes, IPEgressPackets. all t, all "false", all eating. ๐ฅ
and bestie look at the very last line โ there's an @org.freedesktop.DBus.Property.EmitsChangedSignal("false") just sitting there with no property under it. that's not a bug in my typing, that's genuinely where this chunk stops. ๐ญ cliffhanger. the annotation is dangling, waiting for its property, and honestly? same energy. the Service interface has more to say and we are so not done here. ๐ฆ
okay so the property list just keeps going and honestly? respect the commitment. ๐
we're still deep in the Unit interface, so let's keep scrolling through the interface definition together โ same energy, same annotations, no skipping.
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
see how every single one of these carries that @org.freedesktop.DBus.Property.EmitsChangedSignal("false") annotation? yeah. it's the whole vibe of this stretch โ and notice how the Startup* twins keep showing up next to their non-Startup besties like matching outfits. ๐ the symmetry? obsessed.
now the I/O and memory control block, and bestie, it is long. a(st) all over the place, a(st) my beloved. ๐ฆ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
MemoryMin โ MemoryLow โ MemoryHigh โ MemoryMax?? it's giving a whole little ladder of intensity and i for one am here for it. ๐
devices, tasks, and the networking block โ this is where the a(iayu) girlies live. ๐
โจ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
IPAddressAllow and IPAddressDeny sitting right next to each other, both typed a(iayu)... it's giving "we're a matched set and we know it". ๐ญ also OOMKills and ManagedOOMKills from earlier said hi, they're all part of the same OOM saga, iykyk.
BPF, socket binds, network interfaces, and then the pressure watch trio. this chunk has range. ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
okay but the MemoryPressureWatch / CPUPressureWatch / IOPressureWatch triple with their matching *ThresholdUSec partners?? iconic naming, no notes. ๐
and NOW. the annotation changes. ๐ every property so far was "false", but from here on out it's "const", starting with the environment block and then an absolute wall of resource limits. buckle up bestie, this is the finale of the part. ๐ฅ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sb) EnvironmentFiles = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PassEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UnsetEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u UMask = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPU = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPUSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATASoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitAS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitASSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROCSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
the Limit* + Limit*Soft pairs marching down the screen, all readonly t, all "const"... the way that it just keeps pairing up is so satisfying to my little gremlin brain. ๐ง and notice โ LimitMEMLOCK gets its annotation line and then we're cut off mid-list, because bestie, the limits list is NOT done. ๐ซถ it literally keeps going.
heads up: this is exactly where the listing continues โ don't close the fence in your head, the next chunk picks up right after that trailing annotation. no cap. ๐
okay bestie we are still in the property declarations and they just keep going, and honestly? iconic behaviour. every single one of these is readonly and carries that same @org.freedesktop.DBus.Property.EmitsChangedSignal("const") badge, so they're all in the same club. no skips, no shortcuts, here's the whole gang:
readonly t LimitMEMLOCKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDING = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDINGSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIO = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIOSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIME = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIMESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s WorkingDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImage = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) RootImageOptions = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHash = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHashSignature = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashSignaturePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootVerity = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RootEphemeral = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootMStack = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExtensionDirectories = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sba(ss)) ExtensionImages = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssba(ss)) MountImages = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i OOMScoreAdjust = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CoredumpFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Nice = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingClass = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay CPUAffinity = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUAffinityFromNUMA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i NUMAPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay NUMAMask = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUSchedulingResetOnFork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NonBlocking = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay StandardInputData = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardError = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardErrorFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TTYPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYReset = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVHangup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SyslogLevelPrefix = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogLevel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogFacility = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i LogLevelMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LogRateLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogRateLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly aay LogExtraFields = [[...], ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(bs) LogFilterPatterns = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s LogNamespace = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SecureBits = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CapabilityBoundingSet = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t AmbientCapabilities = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s User = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Group = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DynamicUser = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SetLoginEnvironment = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ImportCredential = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) ImportCredentialEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SupplementaryGroups = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PAMName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadWritePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadOnlyPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateTmpEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateDevices = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectClock = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelTunables = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
so like, vibe check on what you just scrolled through ๐ these are all just the D-Bus mirror of the unit file settings, sorted into lil fams so your brain can breathe:
- the resource-limit girlies โ
LimitMEMLOCKSoft,LimitLOCKS,LimitLOCKSSoft,LimitSIGPENDING,LimitSIGPENDINGSoft,LimitMSGQUEUE,LimitMSGQUEUESoft,LimitNICE,LimitNICESoft,LimitRTPRIO,LimitRTPRIOSoft,LimitRTTIME,LimitRTTIMESoft - the filesystem / root / image besties โ
WorkingDirectory,RootDirectory,RootImage,RootImageOptions,RootHash,RootHashPath,RootHashSignature,RootHashSignaturePath,RootVerity,RootEphemeral,RootMStack,ExtensionDirectories,ExtensionImages,MountImages - scheduling, OOM & NUMA era โ
OOMScoreAdjust,CoredumpFilter,Nice,IOSchedulingClass,IOSchedulingPriority,CPUSchedulingPolicy,CPUSchedulingPriority,CPUAffinity,CPUAffinityFromNUMA,NUMAPolicy,NUMAMask,TimerSlackNSec,CPUSchedulingResetOnFork,NonBlocking - stdio & tty mains โ
StandardInput,StandardInputFileDescriptorName,StandardInputData,StandardOutput,StandardOutputFileDescriptorName,StandardError,StandardErrorFileDescriptorName,TTYPath,TTYReset,TTYVHangup,TTYVTDisallocate,TTYRows,TTYColumns - logging (aka the receipts) ๐ โ
SyslogPriority,SyslogIdentifier,SyslogLevelPrefix,SyslogLevel,SyslogFacility,LogLevelMax,LogRateLimitIntervalUSec,LogRateLimitBurst,LogExtraFields,LogFilterPatterns,LogNamespace - identity, creds & capabilities ๐ โ
SecureBits,CapabilityBoundingSet,AmbientCapabilities,User,Group,DynamicUser,SetLoginEnvironment,RemoveIPC,SetCredential,SetCredentialEncrypted,LoadCredential,LoadCredentialEncrypted,ImportCredential,ImportCredentialEx,SupplementaryGroups,PAMName - the sandbox / protection squad ๐ก๏ธ โ
ReadWritePaths,ReadOnlyPaths,InaccessiblePaths,ExecPaths,NoExecPaths,ExecSearchPath,MountFlags,PrivateTmp,PrivateTmpEx,PrivateDevices,ProtectClock,ProtectKernelTunables
notice how the types are doing their own thing too โ t is the unsigned 64-bit one, i signed 32-bit, u unsigned 32-bit, q unsigned 16-bit, b boolean, s string, as array of strings, ay array of bytes, and then the spicy compound ones like a(ss), a(say), a(bs), a(sba(ss)), a(ssba(ss)) and aay for when a single value just wasn't enough โจ copy them exactly if you're hand-rolling a call, bestie, because D-Bus will absolutely humble you if the signature is off by one character ๐ญ
and fr fr, every one of these bad boys says EmitsChangedSignal("const"), so like the ones before it, it's the "this doesn't change after the unit's loaded" energy. no cap.
we are SO not done though, there's more coming ๐
okay so bestie, we are still inside the big D-Bus property dump for the service unit โ and like, every single one of these is readonly, so they're set once and then they simply do not take feedback ๐
. Think permanent personality traits, not moods.
ngl the annotation for ProtectKernelModules got cut in half by the page break โ it lives at the very end of the last part. Same energy, promise. โจ
readonly b ProtectKernelModules = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelLogs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectControlGroups = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectControlGroupsEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateNetwork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateUsers = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateUsersEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateMounts = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivatePIDs = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectHome = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectSystem = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SameProcessGroup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SELinuxContext = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) AppArmorProfile = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SmackProcessLabel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreSIGPIPE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NoNewPrivileges = ...;
sandbox girlies rise up ๐ โ that whole block is the containment clique: Protect*, Private*, and the MAC-label trio (SELinuxContext, AppArmorProfile, SmackProcessLabel) all chillin' with their (bs) struct shapes. And yeah, the -Ex variants are there too, being extra. slay.
next up, the syscall crew ๐ง โ filter, log, arch, error number, all of it, plus the personality situation:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SystemCallArchitectures = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SystemCallErrorNumber = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallLog = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Personality = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LockPersonality = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictAddressFamilies = ...;
like, SystemCallArchitectures is the only as in that bunch โ everybody else is doing a struct or a plain scalar. not me noticing the little type differences ๐
then it's the directory-creation saga ๐ which is honestly so long it deserves its own little era. runtime, state, cache, logs, config โ each one gets a symlink array, a mode, and the state/cache/logs ones ALSO get an accounting flag and a quota struct:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) RuntimeDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RuntimeDirectoryPreserve = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u RuntimeDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RuntimeDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) StateDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConfigurationDirectory = ['...', ...];
the way that ConfigurationDirectory is the only one without a Symlink, a Preserve, an Accounting, or a Quota... it's giving minimal effort and honestly, respect ๐ซถ
and then, the hardening finale ๐ฅ โ cleanup timeouts, memory guards, namespace restrictions, the whole mount situation, keyrings, proc, hostname, BPF delegation, KSM, THP, and all the namespace paths:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutCleanUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryDenyWriteExecute = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictRealtime = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictSUIDSGID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestrictNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DelegateNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictFileSystems = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindReadOnlyPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) TemporaryFileSystem = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MountAPIVFS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b BindLogSockets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KeyringMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectProc = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProcSubset = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectHostname = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (ss) ProtectHostnameEx = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateBPF = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateCommands = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateMaps = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegatePrograms = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateAttachments = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryKSM = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MemoryTHP = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UserNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s NetworkNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s IPCNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...';
RestrictNamespaces and DelegateNamespaces are both t (that's the unsigned-64-bit one, iykyk) โ they're the bitmask besties ๐. And BindPaths/BindReadOnlyPaths share the exact same a(ssbt) shape, which is chef's kiss consistency.
๐จ okay pause. these next three are the rebels of the whole list, because their annotation is "false" instead of "const":
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
not them being the only ones breaking the "const" streak ๐ญ the *Usage properties are lowkey the main characters here, fr fr.
and finally the kill/restart block ๐ โ because every process needs a way out, and systemd is gonna pick it for you:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i KillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i RestartKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGKILL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGHUP = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i WatchdogSignal = ...;
};
all the signal ones are i (signed 32-bit ints, since signals are just lil numbers โจ) and then we hit the closing brace โ the property era is officially over, bestie.
and look at the little encore after it ๐ โ four more interfaces get name-dropped, three of them being the D-Bus basics every object has to carry:
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
org.freedesktop.DBus.Peer, org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties โ the trio that literally every object on the bus has to have, no exceptions, no cap. And then org.freedesktop.systemd1.Unit slides in at the end because, yeah, a service is a unit, the inheritance is giving iconic ๐.
and that }; with all the extra indentation? that's the whole org.freedesktop.systemd1.Service interface shutting its door. periodt. but bestie we are NOT done โ there's more coming ๐
โจ Methods โจ
BindMount()andMountImage()โ bestie, these do the exact same thing as the methods with the same names on the Manager object (scroll up, they're right there ๐ ). The plot twist? These ones live on the service object itself, so they don't take a unit name parameter at all. Now, calling them on the Manager object instead has one lil perk: you skip the wholeGetUnit()call just to grab the unit object for a specific unit name. So yeah, going through the Manager is basically a round trip optimization โ fewer laps around the bus, yk? ๐โโ๏ธ๐จDumpFileDescriptorStore()โ returns an array stuffed with info about all the file descriptors currently chilling in the service's file descriptor store. Each entry is giving:- the file descriptor name (that's the
FDNAME=field), - the file descriptor inode type and access mode as an integer (a
mode_tvalue, so flags likeS_IFREG,S_IRUSR, โฆ), - the major and minor numbers of the device number of the file system backing the inode of the file descriptor,
- the inode number,
- the major and minor numbers of the device number if this refers to a character or block device node,
- a file system path pointing to the inode,
- and the file descriptor flags (you know,
O_RDWR,O_RDONLY, โฆ).
- the file descriptor name (that's the
๐ Properties ๐
Okay so most properties on the Service interface map directly to the corresponding settings in service unit files. No notes, no drama, 1:1, periodt. So for the sake of brevity, here's the list of all the exceptions only ๐:
TimeoutStartUSec,TimeoutStopUSecandTimeoutAbortUSecโ these hold the start, stop and abort timeouts, in microseconds. And ngl, peep the slight naming difference compared to the matching unit file settings (seesystemd.service(5)): these bus properties strictly use microseconds (hence the...USecsuffix) while the unit file settings default to a time unit of seconds (hence...Sec), unless a different unit is explicitly specified. Why tho? Because internally the service manager deals in microsecond units only, and the bus properties are a relatively low-level (binary) concept exposing exactly that. The unit file settings, on the other hand, are relatively high-level (string-based) concepts, so they support more user-friendly time specifications that default to second time units but allow other units too, if you specify them. Iconic layering tbh ๐WatchdogTimestampandWatchdogTimestampMonotonicโ these containCLOCK_REALTIME/CLOCK_MONOTONICmicrosecond timestamps of the last watchdog ping received from the service, or0if none was ever received. No ping, no timestamp, that simple ๐ExecStartPre,ExecStart,ExecStartPost,ExecReload,ExecReloadPost,ExecStop, andExecStopPostโ arrays of structures, and each struct contains:- the binary path to execute;
- an array with all arguments to pass to the executed command, starting with argument
0; - a boolean whether it should be considered a failure if the process exits uncleanly;
- two pairs of
CLOCK_REALTIME/CLOCK_MONOTONICmicrosecond timestamps for when the process began and finished running the last time, or0if it never ran or never finished running; - the PID of the process, or
0if it has not run yet; - the exit code and status of the last run.
So this field maps more or less to the corresponding setting in the service unit file, but it's been augmented with runtime data. Glow up โจ
LimitCPU(and related properties) โ map more or less directly to the corresponding settings in the service unit files, except that if they are not set their value is18446744073709551615(i.e.-1). Yeah that's a real number bestie, it's fine, breathe ๐ซถCapabilitiesโ contains the configured capabilities, as formatted withcap_to_text(3).SecureBits,CapabilityBoundingSet,MountFlagsโ also correspond to the configured settings of the unit files, but instead of being formatted as strings, they are encoded as the actual binary flags they are. Raw. Unfiltered. We love that ๐ExecMainStartTimestamp,ExecMainStartTimestampMonotonic,ExecMainExitTimestamp,ExecMainExitTimestampMonotonic,ExecMainHandoffTimestamp,ExecMainHandoffTimestampMonotonic,ExecMainPID,ExecMainCode,ExecMainStatusโ all the tea about the main process of the service, as far as it is known. TheExecMainStartTimestamptimestamps record when the main process of the service is created. TheExecMainExitTimestamptimestamps record when the main process exit has been detected by the service manager. TheExecMainHandoffTimestamptimestamps record when the service binary is about to be executed bysystemd-executor(and bestie, this timestamp gets recorded regardless of whether the immediately followingexecve()system call succeeds or fails โ no cap). This is often the same runtime information that's also maintained forExecStart=. However, it deviates for services withType=forkingas well as services that useMAINPID=sd_notify()messages, because in that case the main process of the service is not forked off by the service manager directly. These fields either contain information of the last run of the process or of the current running process. Either way, receipts ๐MainPIDandControlPIDโ the main and control PID of the service. The main PID is the current main PID of the service, and it's0when the service currently has no main PID. The control PID is the PID of the current start/stop/reload process running, and it's0if no such process is currently running. So that meansExecMainPIDandMainPIDdiffer in that the latter immediately reflects whether a main process is currently running, while the former possibly contains information collected from the last run even if the process is no longer around. One is live, one is a memory ๐ญStatusText,StatusErrno,StatusBusError, andStatusVarlinkErrorโ these contain the status text, the error number, and the D-Bus/Varlink error name passed to the service manager viasd_notify(3), respectively. Services can use them to inform the service manager about their internal state. Like a lil mood update in the group chat ๐ฒResultโ encodes the execution result of the last run of the service. It's genuinely useful for figuring out why a service failed if it's in the"failed"state (peepActiveStateabove ๐). The following values are currently known:"success"โ set if the unit did not fail. We love a clean run โจ"resources"โ not enough resources were available to fork off and execute the service processes."timeout"โ a timeout occurred while executing a service operation."exit-code"โ a service process exited with an unclean exit code."signal"โ a service process exited with an uncaught signal."core-dump"โ a service process exited uncleanly and dumped core."watchdog"โ a service did not send out watchdog ping messages often enough. Rude of it, honestly."start-limit-hit"โ a service has been started too frequently in a specific time frame (as configured inStartLimitInterval,StartLimitBurst)."oom-kill"โ a service was terminated due to an out-of-memory (OOM) situation. ๐ญ
ControlGroupโ indicates the control group path the processes of this service unit are placed in. Their lil neighborhood ๐ก- The following properties map 1:1 to corresponding settings in the unit file:
RootDirectoryRootImageRootImageOptionsRootVerityRootHashRootHashSignatureMountImagesExtensionImagesExtensionDirectoriesRootMStackโ seesystemd.exec(5)for their meaning. MemoryAvailableโ takes into account the unit's and parents'"MemoryMax"or"MemoryHigh"or physically available RAM versus the given level's memory consumption, and takes the minimum. โ ๏ธ Beware: other units below the tightest parent slice may consume the memory quicker and less than the reported value would remain for your own allocation. It works better in conjunction withMemoryAccounting=yeson the involved units. Fr fr, don't trust it blindly ๐DelegateSubgroupโ contains the cgroup subgroup to place invoked unit processes in. As configured by the option of the same name in unit files. This is set to the empty string when it does not apply or no subgroup has been configured.RuntimeDirectorySymlink,StateDirectorySymlink,CacheDirectorySymlinkandLogsDirectorySymlinkโ respectively implement the destination parameter of the unit files settingsRuntimeDirectory,StateDirectory,CacheDirectoryandLogsDirectory, which will create a symlink of the given name to the respective directory. The messages take a flags parameter that make the directory read only:
#define SD_EXEC_DIRECTORY_READ_ONLY (UINT64_C(1) << 0)
ExtraFileDescriptorNamesโ contains file descriptor names passed to the service via theExtraFileDescriptorsproperty in theStartTransientUnit()method. Seesd_listen_fds(3)for more details on how to retrieve these file descriptors. And unlike theExtraFileDescriptorsinput property,ExtraFileDescriptorNamesonly contains names and not the file descriptors. Names only, bestie, the fds stay home ๐ManagedOOMMemoryPressureDurationUSecโ implements the destination parameter of the unit file settingManagedOOMMemoryPressureDurationSec=listed insystemd.resource-control(5). Note the time unit is expressed in"ฮผs".ProtectControlGroupsExโ implements the destination parameter of the unit file settingProtectControlGroups=listed insystemd.exec(5). Unlike the booleanProtectControlGroups,ProtectControlGroupsExis a string type.PrivatePIDsโ implements the destination parameter of the unit file settingPrivatePIDs=listed insystemd.exec(5). NotePrivatePIDsis a string type to allow adding more values in the future. Future-proof queen ๐ProtectHostnameExโ implements the destination parameter of the unit file settingProtectHostname=listed insystemd.exec(5). Unlike the booleanProtectHostname,ProtectHostnameExis a pair of strings: the first one is a boolean string or the special value"private", and the second one is an optional private hostname that will be set in a new UTS namespace for the unit. Two strings, one namespace, so much lore ๐ธ
โจ SOCKET UNIT OBJECTS โจ
bestie. okay. sit down. hydrate. because this is the socket unit era and it is a lot of properties. ๐
A socket unit exposes itself on the bus at a node path that looks like this, where the unit name gets escaped (- becomes _2d, . becomes _2e), so avahi-daemon.socket shows up as avahi_2ddaemon_2esocket:
node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
interface org.freedesktop.systemd1.Socket {
methods:
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BindIPv6Only = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u Backlog = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BindToDevice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SocketUser = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SocketGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u SocketMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Accept = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b FlushPending = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Writable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b KeepAlive = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t KeepAliveTimeUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t KeepAliveIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u KeepAliveProbes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DeferAcceptUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NoDelay = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Priority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t ReceiveBuffer = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t SendBuffer = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IPTOS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IPTTL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PipeSize = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b FreeBind = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Transparent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Broadcast = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassCredentials = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassPIDFD = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassSecurity = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassPacketInfo = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b AcceptFileDescriptors = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Timestamping = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveOnStop = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) Listen = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Symlinks = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) XAttrEntryPoint = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) XAttrListen = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) XAttrAccept = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Mark = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u MaxConnections = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u MaxConnectionsPerSource = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly x MessageQueueMaxMessages = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly x MessageQueueMessageSize = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TCPCongestion = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ReusePort = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SmackLabel = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SmackLabelIPIn = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SmackLabelIPOut = '...';
readonly u ControlPID = ...;
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NConnections = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NAccepted = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NRefused = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s FileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SocketProtocol = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TriggerLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u TriggerLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t PollLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u PollLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s DeferTrigger = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DeferTriggerMaxUSec = ...;
readonly u UID = ...;
readonly u GID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PassFileDescriptorsToExec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStartPre = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStartPost = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStopPre = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecStopPost = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
Okay so yes, that's the vibe. ๐ธ Now let's actually walk it because there is SO much here.
๐ซถ Methods
GetProcessesโ takes no inputs and hands you backa(sus) processes. Cute little tuple situation, iykyk.AttachProcessesโ you give its subcgroupandau pids, and that's it. No return value, it just does the thing.RemoveSubgroupโ you give its subcgroupandt flags. Also no return value. Bye girl ๐
๐ Properties
Heads up bestie: almost every single one of these is @org.freedesktop.DBus.Property.EmitsChangedSignal("const"), which means they're set in stone once the unit loads and the signal doesn't fire for them. A few are "false" (they change, but no signal announcement, so you gotta go look yourself), a few are "invalidates", and a couple have no annotation at all. I'm flagging each one so you never get caught slipping. โจ
๐ The const crew
BindIPv6Onlyโs,"const"Backlogโu,"const"TimeoutUSecโt,"const"BindToDeviceโs,"const"SocketUserโs,"const"SocketGroupโs,"const"SocketModeโu,"const"DirectoryModeโu,"const"Acceptโb,"const"FlushPendingโb,"const"Writableโb,"const"KeepAliveโb,"const"KeepAliveTimeUSecโt,"const"KeepAliveIntervalUSecโt,"const"KeepAliveProbesโu,"const"DeferAcceptUSecโt,"const"NoDelayโb,"const"Priorityโi,"const"ReceiveBufferโt,"const"SendBufferโt,"const"IPTOSโi,"const"IPTTLโi,"const"PipeSizeโt,"const"FreeBindโb,"const"Transparentโb,"const"Broadcastโb,"const"PassCredentialsโb,"const"PassPIDFDโb,"const"PassSecurityโb,"const"PassPacketInfoโb,"const"AcceptFileDescriptorsโb,"const"Timestampingโs,"const"RemoveOnStopโb,"const"Listenโa(ss),"const", shows up as a list of pairs like[...]Symlinksโas,"const", that's a list of strings, looks like['...', ...]XAttrEntryPointโa(ss),"const",[...]XAttrListenโa(ss),"const",[...]XAttrAcceptโa(ss),"const",[...]Markโi,"const"MaxConnectionsโu,"const"MaxConnectionsPerSourceโu,"const"MessageQueueMaxMessagesโx,"const"MessageQueueMessageSizeโx,"const"TCPCongestionโs,"const"ReusePortโb,"const"SmackLabelโs,"const"SmackLabelIPInโs,"const"SmackLabelIPOutโs,"const"SocketProtocolโi,"const"TriggerLimitIntervalUSecโt,"const"TriggerLimitBurstโu,"const"PollLimitIntervalUSecโt,"const"PollLimitBurstโu,"const"DeferTriggerโs,"const"DeferTriggerMaxUSecโt,"const"PassFileDescriptorsToExecโb,"const"
๐ธ The no-annotation girlies
These ones just say readonly and nothing else, no signal gossip attached:
ControlPIDโuResultโsUIDโuGIDโu
๐ฆ The "false" squad (no change signal, go look yourself)
NConnectionsโu,"false"NAcceptedโu,"false"NRefusedโu,"false"FileDescriptorNameโs,"false"Sliceโs,"false"ControlGroupโs,"false"ControlGroupIdโt,"false"MemoryCurrentโt,"false"MemoryPeakโt,"false"MemorySwapCurrentโt,"false"MemorySwapPeakโt,"false"MemoryZSwapCurrentโt,"false"MemoryAvailableโt,"false"EffectiveMemoryMaxโt,"false"EffectiveMemoryHighโt,"false"CPUUsageNSecโt,"false"EffectiveCPUsโay,"false",[...]EffectiveMemoryNodesโay,"false",[...]TasksCurrentโt,"false"EffectiveTasksMaxโt,"false"IPIngressBytesโt,"false"IPIngressPacketsโt,"false"IPEgressBytesโt,"false"IPEgressPacketsโt,"false"IOReadBytesโt,"false"IOReadOperationsโt,"false"IOWriteBytesโt,"false"IOWriteOperationsโt,"false"OOMKillsโt,"false"
๐ The "invalidates" ones
These four are a(sasbttttuii), they show up as [...], and they invalidate instead of doing a cute little change ping:
ExecStartPreโa(sasbttttuii),"invalidates"ExecStartPostโa(sasbttttuii),"invalidates"ExecStopPreโa(sasbttttuii),"invalidates"ExecStopPostโa(sasbttttuii),"invalidates"
And then the code block just. ends. mid-property, dangling on an annotation with nothing after it. Not me getting left on read by the manpage ๐ Keep reading bestie, there's more coming.
...and the list just keeps going, bestie. We're still deep in the resource-control properties, so buckle up ๐
readonly t ManagedOOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
okay so that whole chunk is giving "no signal" energy โ every single one of them is tagged @org.freedesktop.DBus.Property.EmitsChangedSignal("false"), which is D-Bus's way of saying don't expect me to ping you when this changes. They're still readonly, they still exist, they just don't announce themselves. lowkey mysterious of them ๐
Then the annotations switch up. Meet the const crew โจ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sb) EnvironmentFiles = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PassEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UnsetEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u UMask = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPU = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPUSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATASoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitAS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitASSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROCSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDING = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDINGSoft = ...;
so like. the environment stuff โ Environment, EnvironmentFiles, PassEnvironment, UnsetEnvironment โ and the UMask plus that whole iconic Limitโฆ family (every one of them paired with its โฆSoft sibling, no cap, they come in twos ๐ซถ) are all annotated "const". Same readonly treatment, different annotation. periodt.
and yes, we're still not done, bestie โ more properties are coming in the next bit ๐
okay so we are still deep in the property wall bestie, and this whole stretch is just @org.freedesktop.DBus.Property.EmitsChangedSignal("const") over and over โ it's giving very much "same energy, different property name" ๐
every single one of these is tagged const, and we do not skip a single one. first up, the resource-limit girlies ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIO = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIOSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIME = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIMESoft = ...;
see how they all come in little pairs? โจ the plain one and the ...Soft one, like a matched set, obsessed. and every one of them is a t, okay, noted, moving on ๐ซถ
then we get the directory-and-root section, which is lowkey the longest glow-up in this whole chunk โ working dirs, root dirs, root images, hashes, verity, and then the extension/mount image trio at the end ๐ธ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s WorkingDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImage = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) RootImageOptions = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHash = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHashSignature = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashSignaturePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootVerity = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RootEphemeral = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootMStack = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExtensionDirectories = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sba(ss)) ExtensionImages = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssba(ss)) MountImages = [...];
like look at a(sba(ss)) and a(ssba(ss)) โ those signatures are doing the MOST and honestly? iconic. ๐ฆ
next: scheduling and priorities, aka the "who gets the CPU and who waits" chapter. OOM scores, coredump filters, nice, io scheduling, cpu scheduling, affinity, NUMA, timer slack, and the two little booleans at the bottom ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i OOMScoreAdjust = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CoredumpFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Nice = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingClass = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay CPUAffinity = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUAffinityFromNUMA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i NUMAPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay NUMAMask = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUSchedulingResetOnFork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NonBlocking = ...;
then the stdio / TTY / logging era ๐ we've got standard input, output and error (each with its own FileDescriptorName, cute), the TTY properties including TTYRows and TTYColumns which are typed q, and then the whole syslog + log cluster at the bottom, finishing on LogNamespace. not me getting emotional over LogExtraFields being a aay ๐ฅน
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay StandardInputData = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardError = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardErrorFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TTYPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYReset = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVHangup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SyslogLevelPrefix = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogLevel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogFacility = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i LogLevelMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LogRateLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogRateLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly aay LogExtraFields = [[...], ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(bs) LogFilterPatterns = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s LogNamespace = '...';
and now we roll into the user / credentials / sandbox zone, which is where the real main character energy lives ๐ secure bits, capability bounding sets, ambient capabilities, user, group, dynamic user, login environment, IPC removal, then the entire credential saga (SetCredential, SetCredentialEncrypted, LoadCredential, LoadCredentialEncrypted, ImportCredential, ImportCredentialEx โ bestie they really said "one credential option is not enough"), supplementary groups, PAM name, and the whole path-permission parade ๐ฆ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SecureBits = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CapabilityBoundingSet = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t AmbientCapabilities = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s User = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Group = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DynamicUser = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SetLoginEnvironment = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ImportCredential = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) ImportCredentialEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SupplementaryGroups = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PAMName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadWritePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadOnlyPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateTmpEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateDevices = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectClock = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelTunables = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelModules = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelLogs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectControlGroups = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectControlGroupsEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateNetwork = ...;
okay and the Protect* booleans all stacked up at the end like a little row of shields? ๐ก๏ธ adorable, protective, exactly the vibe. and we end this part right on PrivateNetwork, which is honestly the perfect cliffhanger, because bestie there is still SO much more of this property list to go โ so don't go anywhere ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateUsers = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateUsersEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateMounts = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivatePIDs = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectHome = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectSystem = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SameProcessGroup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SELinuxContext = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) AppArmorProfile = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SmackProcessLabel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreSIGPIPE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NoNewPrivileges = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SystemCallArchitectures = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SystemCallErrorNumber = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallLog = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Personality = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LockPersonality = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictAddressFamilies = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) RuntimeDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RuntimeDirectoryPreserve = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u RuntimeDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RuntimeDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) StateDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConfigurationDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutCleanUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryDenyWriteExecute = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictRealtime = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictSUIDSGID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestrictNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DelegateNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictFileSystems = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindReadOnlyPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) TemporaryFileSystem = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MountAPIVFS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b BindLogSockets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KeyringMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectProc = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProcSubset = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectHostname = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (ss) ProtectHostnameEx = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateBPF = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateCommands = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateMaps = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegatePrograms = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateAttachments = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryKSM = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MemoryTHP = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UserNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s NetworkNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s IPCNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i KillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i RestartKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGKILL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGHUP = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i WatchdogSignal = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
okay so that's the rest of the execution-context property wall ๐
bestie, and yes, the closing braces are exactly like that โ the Service interface ends with };, and then the other interfaces (org.freedesktop.DBus.Peer, org.freedesktop.DBus.Introspectable, org.freedesktop.DBus.Properties, and org.freedesktop.systemd1.Unit) each get their own little { ... }; cameo inside the same object, and the whole object closes out with };. the way that's just nesting all the way down... iconic, honestly ๐ธ
the PollLimitIntervalUSec and PollLimitBurst properties configure the polling limit for the socket unit ๐
PollLimitIntervalUSecexpects a time in ยตsPollLimitBurstexpects an unsigned integer
and if either one of them is set to zero, the limiting feature is turned off ๐ no cap, zero means off, not "zero of a thing".
โจ Properties โจ
ngl, most of these properties are just a 1:1 glow-up of the settings you already know from socket unit files ๐ฆ like, you write it in the unit file, it shows up here, they're the same facts in a cuter outfit.
also โ and this is the part people forget โ socket units can include ExecStartPre (and similar) fields, and those fields contain info about processes to execute ๐ซถ so socket units also share most of the fields related to the execution context that Service objects expose. see above for all of that โฌ๏ธ (it's a lot, I know, but we got through it together).
and on top of all of those properties, there are the following:
cue the next part, bestie ๐ง
NAccepted is the lil counter of every connection this socket has ever accepted, like all-time, no take-backs ๐. But bestie, heads up: this only counts for sockets where Accept is set to "yes", aka the ones where systemd is the one doing the accepting. If systemd isn't the acceptor, this number is just vibing at zero, not relevant to you โจ.
NConnections is the currently open connections on this socket โ like, right now, the live ones ๐ซถ. Same deal as above: it only applies to socket units with Accept set to "yes". No accept, no count, periodt.
Result is the tea on why a socket unit failed if it's sitting in the "failed" state (peep ActiveState above ๐). The values are:
"success""resources""timeout""exit-code""signal""core-dump"
โฆand these mean exactly what they mean for the matching field on service units (see above, iykyk). AND there's one extra: "service-failed-permanent" means the service of this socket failed continuously โ like it just kept failing, no cap ๐ญ.
FlushPending says whether to flush the socket right before it enters the listening state. Lowkey important: this setting only applies to sockets with Accept= set to "no". So if you're in accept-yes land, this does nothing for you, sorry bestie ๐.
XAttrEntryPoint, XAttrListen and XAttrAccept each hold a list of extended attributes (as "NAME"/"VALUE" pairs) to slap onto socket inodes ๐
. Here's the breakdown:
- XAttrEntryPoint applies to the file-system inode an AF_UNIX socket is bound to.
- XAttrListen applies to the listening socket.
- XAttrAccept applies to connection sockets accepted off the listening socket.
For all the deets, go read the XAttrEntryPoint=, XAttrListen= and XAttrAccept= settings in systemd.socket(5) ๐.
๐ฏ TARGET UNIT OBJECTS ๐ฏ
node /org/freedesktop/systemd1/unit/basic_2etarget {
interface org.freedesktop.systemd1.Target {
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
Target units have neither type-specific methods nor properties โ they're the chill minimalist icon of the unit world, just vibes, nothing else โจ.
๐ป DEVICE UNIT OBJECTS ๐ป
Every device unit object implements the org.freedesktop.systemd1.Device interface (described right here, bestie) plus the generic org.freedesktop.systemd1.Unit interface (see above ๐).
node /org/freedesktop/systemd1/unit/dev_2dttyS0_2edevice {
interface org.freedesktop.systemd1.Device {
properties:
readonly s SysFSPath = '...';
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
โจ Properties โจ
Device units are keeping it cute and only expose one single type-specific property ๐:
- SysFSPath โ holds the sysfs path of the kernel device this object corresponds to ๐ฅ.
๐ MOUNT UNIT OBJECTS ๐
Every mount unit object implements the org.freedesktop.systemd1.Mount interface (described right here, bestie) plus the generic org.freedesktop.systemd1.Unit interface (see above ๐).
okay so here's the actual shape of a mount unit on the bus, bestie. Every property, every annotation, every method โ laid out exactly like the introspection hands it over. ๐
node /org/freedesktop/systemd1/unit/home_2emount {
interface org.freedesktop.systemd1.Mount {
methods:
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Where = '...';
readonly s What = '...';
readonly s Options = '...';
readonly s Type = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutUSec = ...;
readonly u ControlPID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SloppyOptions = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LazyUnmount = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ForceUnmount = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ReadWriteOnly = ...;
readonly s Result = '...';
readonly s ReloadResult = '...';
readonly s CleanResult = '...';
readonly u UID = ...;
readonly u GID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecMount = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecUnmount = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecRemount = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
<h3>๐ธ the little bits at the top ๐ธ</h3>
The mount unit inherits a few methods from the unit interface, and they're right there at the top of the listing:
GetProcesses(out a(sus) processes)โ hands you back the processes asa(sus).AttachProcesses(in s subcgroup, in au pids)โ takes asubcgroupand a list ofpids.RemoveSubgroup(in s subcgroup, in t flags)โ takes asubcgroupandflags.
so tidy, so demure, so mindful ๐
<h3>๐ฆ the mount-specific properties ๐ฆ</h3>
These are the ones that make it a mount and not just any old unit:
Where,What,Options,Typeโ all plainsstrings, andWhereis markedconst.TimeoutUSec(t,const) andControlPID(u).DirectoryMode(u,const).SloppyOptions,LazyUnmount,ForceUnmount,ReadWriteOnlyโ allb, allconst.Result,ReloadResult,CleanResultโ three separatesstrings, one per flavour of outcome.UIDandGIDโ bothu.ExecMount,ExecUnmount,ExecRemountโ the big ones, eacha(sasbttttuii), and each tagged@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates").
<h3>โญ and then... the long haul โญ</h3>
After that it's every single resource-control and accounting property you could possibly want, all of them tagged @org.freedesktop.DBus.Property.EmitsChangedSignal("false"), all readonly, and all just vibing in a very long column. We're talking Slice, ControlGroup, ControlGroupId, the whole memory family (MemoryCurrent, MemoryPeak, MemorySwapCurrent, MemorySwapPeak, MemoryZSwapCurrent, MemoryAvailable, EffectiveMemoryMax, EffectiveMemoryHigh), the CPU gang (CPUUsageNSec, EffectiveCPUs, EffectiveMemoryNodes, CPUWeight, StartupCPUWeight, CPUQuotaPerSecUSec, CPUQuotaPeriodUSec, AllowedCPUs, StartupAllowedCPUs, AllowedMemoryNodes, StartupAllowedMemoryNodes, CPUSetPartition), the task counters (TasksCurrent, EffectiveTasksMax), the network counters (IPIngressBytes, IPIngressPackets, IPEgressBytes, IPEgressPackets), the IO counters and knobs (IOReadBytes, IOReadOperations, IOWriteBytes, IOWriteOperations, IOAccounting, IOWeight, StartupIOWeight, IODeviceWeight, IOReadBandwidthMax, IOWriteBandwidthMax, IOReadIOPSMax, IOWriteIOPSMax, IODeviceLatencyTargetUSec), the OOM drama (OOMKills, ManagedOOMKills, ManagedOOMSwap, ManagedOOMMemoryPressure, ManagedOOMMemoryPressureLimit, ManagedOOMMemoryPressureDurationUSec, ManagedOOMPreference, OOMRules), the delegation set (Delegate, DelegateControllers, DelegateSubgroup), the memory limits with all their Startup* twins (MemoryMin, MemoryLow, StartupMemoryLow, MemoryHigh, StartupMemoryHigh, MemoryMax, StartupMemoryMax, MemorySwapMax, StartupMemorySwapMax, MemoryZSwapMax, StartupMemoryZSwapMax, MemoryZSwapWriteback), the device policy (DevicePolicy, DeviceAllow), the task accounting (TasksAccounting, TasksMax), the IP accounting (IPAccounting, IPAddressAllow, IPAddressDeny, IPIngressFilterPath, IPEgressFilterPath), and DisableControllers.
it's giving "I contain multitudes" and honestly? iconic.
And right at the very end the listing cuts off mid-annotation โ one lonely @org.freedesktop.DBus.Property.EmitsChangedSignal("false") sitting there with its property still on the way. ๐ซถ Hold that thought, bestie, because the next bit picks it right up.
okay so we are STILL deep in the property list and bestie it does not stop, it just keeps going, and every single line is load-bearing so we're reading all of them ๐
first up, the batch that's tagged EmitsChangedSignal("false") โ the introspection data itself is out here saying "don't hold your breath for a changed signal on these":
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
notice the little throuple situation with MemoryPressureWatch, CPUPressureWatch and IOPressureWatch โ three strings, each with its own t (that's a uint64, bestie, big number energy) threshold companion measured in microseconds. and RestrictNetworkInterfaces is the only one up there rocking a (bas) signature, while SocketBindAllow and SocketBindDeny are twins with a(iiqq). iconic. โจ
then the vibe shifts HARD, because everything from here down is tagged EmitsChangedSignal("const") instead. the environment-and-limits block, let's go:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sb) EnvironmentFiles = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PassEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UnsetEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u UMask = ...;
Environment, PassEnvironment and UnsetEnvironment are all as โ arrays of strings, three of them, all about the environment, all const. and EnvironmentFiles is a(sb), a little array-of-struct action. UMask is a lone u (uint32) holding it down by itself. ๐ซถ
and NOW, the main event, the reason your eyes are about to glaze over: THE LIMITS. every one of them a t, every one of them const, and every single one of them comes with a ...Soft sibling. all twenty of them. no cap, we're listing every last one:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPU = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPUSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATASoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitAS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitASSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROCSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDING = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDINGSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIO = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIOSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIME = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIMESoft = ...;
look at that. LimitCPU/LimitCPUSoft, LimitFSIZE/LimitFSIZESoft, LimitDATA/LimitDATASoft, LimitSTACK/LimitSTACKSoft, LimitCORE/LimitCORESoft, LimitRSS/LimitRSSSoft, LimitNOFILE/LimitNOFILESoft, LimitAS/LimitASSoft, LimitNPROC/LimitNPROCSoft, LimitMEMLOCK/LimitMEMLOCKSoft, LimitLOCKS/LimitLOCKSSoft, LimitSIGPENDING/LimitSIGPENDINGSoft, LimitMSGQUEUE/LimitMSGQUEUESoft, LimitNICE/LimitNICESoft, LimitRTPRIO/LimitRTPRIOSoft, LimitRTTIME/LimitRTTIMESoft. seventeen pairs, thirty-four properties, all t, all const, all with the identical annotation line above them like they're in uniform. ate and left no crumbs. ๐
okay, breathe. ๐ง now we get into the filesystem-rooting-and-images section, and the type signatures get SPICY:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s WorkingDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImage = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) RootImageOptions = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHash = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHashSignature = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashSignaturePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootVerity = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RootEphemeral = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootMStack = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExtensionDirectories = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sba(ss)) ExtensionImages = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssba(ss)) MountImages = [...];
so we've got strings galore (WorkingDirectory, RootDirectory, RootImage, RootHashPath, RootHashSignaturePath, RootVerity, RootMStack), two ay byte arrays (RootHash and RootHashSignature โ raw bytes, no strings attached, literally), one b boolean (RootEphemeral), one as (ExtensionDirectories), and then the two absolute UNITS: ExtensionImages with a(sba(ss)) and MountImages with a(ssba(ss)). look at those nested signatures. a(ssba(ss)). that's four things inside a struct inside an array. she's doing a lot and she's doing it well. ๐
and we roll straight on into the scheduling / resource-flavouring block, still all const, still not slowing down:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i OOMScoreAdjust = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CoredumpFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Nice = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingClass = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay CPUAffinity = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUAffinityFromNUMA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i NUMAPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay NUMAMask = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUSchedulingResetOnFork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NonBlocking = ...;
OOMScoreAdjust, Nice, IOSchedulingClass, IOSchedulingPriority, CPUSchedulingPolicy, CPUSchedulingPriority, NUMAPolicy โ all i, all signed 32-bit ints. CPUAffinity and NUMAMask are ay. CPUAffinityFromNUMA, CPUSchedulingResetOnFork and NonBlocking are b. and CoredumpFilter and TimerSlackNSec are the only ts in this bunch, keeping the pattern alive. ๐
and the last stretch for this part โ standard I/O, TTY, and syslog. the plumbing. the "where does the output even go" department:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay StandardInputData = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardError = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardErrorFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TTYPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYReset = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVHangup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SyslogLevelPrefix = ...;
the trio pattern is so clean here: StandardInput + StandardInputFileDescriptorName, StandardOutput + StandardOutputFileDescriptorName, StandardError + StandardErrorFileDescriptorName โ and only the input one gets a bonus ay in the form of StandardInputData. the TTY gang: TTYPath is s, TTYReset / TTYVHangup / TTYVTDisallocate are b, and then TTYRows and TTYColumns show up as q โ that's uint16, the smallest of the integer types here, which honestly makes sense for a row count, lowkey adorable. ๐
and then SyslogPriority (i), SyslogIdentifier (s), and SyslogLevelPrefix (b) walk us right up to the edge of this partโฆ and we are not done, bestie. there's more list after this. obviously there's more list. there's always more list. ๐
...and the property pile keeps going, bestie ๐ we are still in Service unit properties, and this stretch is the stretch โ logging knobs, credentials, sandboxing, directories, syscall filters, all of it. Every single one of these carries the exact same @org.freedesktop.DBus.Property.EmitsChangedSignal("const") annotation, over and over, like a little stamp. Not me being obsessed with how consistent it is ๐ญ
First up, the logging girlies:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogLevel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogFacility = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i LogLevelMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LogRateLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogRateLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly aay LogExtraFields = [[...], ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(bs) LogFilterPatterns = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s LogNamespace = '...';
Then we get into identity and credentials โ who the service runs as, which caps it gets, and every flavour of credential the thing can carry. Look at SetCredential, SetCredentialEncrypted, LoadCredential, LoadCredentialEncrypted, ImportCredential, ImportCredentialEx โ six whole credential options, she's thorough ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SecureBits = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CapabilityBoundingSet = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t AmbientCapabilities = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s User = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Group = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DynamicUser = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SetLoginEnvironment = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ImportCredential = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) ImportCredentialEx = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SupplementaryGroups = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PAMName = '...';
Paths next!! ๐ฆ read-write, read-only, inaccessible, exec, no-exec, and the search path. Six of them, all as (arrays of strings), all lined up like little soldiers:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadWritePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadOnlyPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
And now the big sandbox section โ this is the main character energy part of the whole page, fr fr. Mount flags, private tmp, private devices, protecting the clock, kernel tunables, kernel modules, kernel logs, control groups, network, users, mounts, IPC, PIDs, home, system. Notice the Ex variants โ PrivateTmpEx, ProtectControlGroupsEx, PrivateUsersEx โ she's got layers ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateTmpEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateDevices = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectClock = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelTunables = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelModules = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelLogs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectControlGroups = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectControlGroupsEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateNetwork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateUsers = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateUsersEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateMounts = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivatePIDs = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectHome = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectSystem = '...';
Then some terminal + security-label things, plus IgnoreSIGPIPE and NoNewPrivileges. The security ones are all (bs) โ a boolean and a string hanging out together ๐ซถ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SameProcessGroup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SELinuxContext = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) AppArmorProfile = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SmackProcessLabel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreSIGPIPE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NoNewPrivileges = ...;
Syscall + personality + address families. SystemCallFilter and SystemCallLog are both (bas) โ boolean, array of strings, string. Restrict those address families, bestie, we don't know them like that ๐ฅ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SystemCallArchitectures = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SystemCallErrorNumber = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallLog = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Personality = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LockPersonality = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictAddressFamilies = ...;
Okay and now the directories block โ this one is long, and honestly iconic. Runtime, State, Cache, Logs, Configuration. Each one has its own symlink property (a(sst)), its own mode, its own accounting boolean, and its own quota (tus), then the plain as list. Runtime gets a RuntimeDirectoryPreserve string instead of an accounting flag, because she's special ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) RuntimeDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RuntimeDirectoryPreserve = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u RuntimeDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RuntimeDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) StateDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConfigurationDirectory = ['...', ...];
Lowkey note: ConfigurationDirectory gets a mode and a list but no symlink, no accounting and no quota. That's just how it's written here, bestie โ don't @ me, I'm only telling you what the page says ๐
And to close out this chunk: a cleanup timeout plus the final run of restriction toggles. RestrictFileSystems is (bas), same shape as the syscall filters above, and DelegateNamespaces and RestrictNamespaces are both t.
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutCleanUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryDenyWriteExecute = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictRealtime = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictSUIDSGID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestrictNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DelegateNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictFileSystems = ...;
Okay phew ๐ญ that was a whole cardio session of properties. Every last one of them is readonly, every last one is @org.freedesktop.DBus.Property.EmitsChangedSignal("const"), and every last one is still sitting inside the Service unit object. There's more coming, so don't go anywhere ๐ธ
okay so the mount unit's property dump just keeps going, bestie, and here's the rest of it ๐
every one of these is @org.freedesktop.DBus.Property.EmitsChangedSignal("const") unless it says otherwise:
readonly a(ssbt) BindPaths = [...];
readonly a(ssbt) BindReadOnlyPaths = [...];
readonly a(ss) TemporaryFileSystem = [...];
readonly b MountAPIVFS = ...;
readonly b BindLogSockets = ...;
readonly s KeyringMode = '...';
readonly s ProtectProc = '...';
readonly s ProcSubset = '...';
readonly b ProtectHostname = ...;
readonly (ss) ProtectHostnameEx = ...;
readonly s PrivateBPF = '...';
readonly s BPFDelegateCommands = '...';
readonly s BPFDelegateMaps = '...';
readonly s BPFDelegatePrograms = '...';
readonly s BPFDelegateAttachments = '...';
readonly b MemoryKSM = ...;
readonly s MemoryTHP = '...';
readonly s UserNamespacePath = '...';
readonly s NetworkNamespacePath = '...';
readonly s IPCNamespacePath = '...';
readonly s RootImagePolicy = '...';
readonly s MountImagePolicy = '...';
readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i KillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i RestartKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGKILL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGHUP = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i WatchdogSignal = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
and THAT'S the whole mount node, slayed โจ
๐ธ Properties ๐ธ
most of these properties are literally just the matching settings from the mount unit files, mapped straight over ๐ซถ but here's the lil twist: since mount units actually run the /usr/bin/mount command, their bus objects carry implicit ExecMount fields (and similar ones, iykyk) that hold info about the processes to execute. they also share most of the execution-context fields that Service objects expose โ scroll up for those, bestie ๐
and on top of all that, here's the extra stuff:
ControlPIDโ the PID of the/usr/bin/mountor/usr/bin/umountcommand that's currently running, if one is. no process going? then it's just0๐Resultโ spills the tea on why a mount unit failed, if it failed. it can be"success","resources","timeout","exit-code","signal", or"core-dump", and those mean exactly the same thing as the matching values on the corresponding field of service unit objects (see above ๐).
๐ฆ AUTOMOUNT UNIT OBJECTS ๐ฆ
every automount unit object implements the org.freedesktop.systemd1.Automount interface (described here) plus the generic org.freedesktop.systemd1.Unit interface (see above). the whole package, no crumbs ๐
node /org/freedesktop/systemd1/unit/proc_2dsys_2dfs_2dbinfmt_5fmisc_2eautomount {
interface org.freedesktop.systemd1.Automount {
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Where = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtraOptions = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DirectoryMode = ...;
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutIdleUSec = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
๐ Properties ๐
most of the properties map directly onto the matching settings in the automount unit files. simple as that โจ
Result only knows the values "success" and "resources" at this time, and they mean the same thing as the matching values on the corresponding field of the Service object.
โฐ TIMER UNIT OBJECTS โฐ
every timer unit object implements the org.freedesktop.systemd1.Timer interface (described here) and the generic org.freedesktop.systemd1.Unit interface (see above). okay so the timer is lowkey the main character here, no cap ๐๐
node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer {
interface org.freedesktop.systemd1.Timer {
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Unit = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(stt) TimersMonotonic = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sst) TimersCalendar = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b OnClockChange = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b OnTimezoneChange = ...;
readonly t NextElapseUSecRealtime = ...;
readonly t NextElapseUSecMonotonic = ...;
readonly t LastTriggerUSec = ...;
readonly t LastTriggerUSecMonotonic = ...;
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t AccuracyUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RandomizedDelayUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RandomizedOffsetUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b FixedRandomDelay = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b Persistent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b WakeSystem = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemainAfterElapse = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DeferReactivation = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
โจ Properties โจ
Unitโ holds the name of the unit that gets activated when the timer elapses. that's the whole point, periodt ๐TimersMonotonicโ an array of structs holding info about all the monotonic timers on this timer unit. each struct has: a string naming the timer base โ one of"OnActiveUSec","OnBootUSec","OnStartupUSec","OnUnitActiveUSec", or"OnUnitInactiveUSec", which line up with the settings of the same names in the timer unit files; the microsecond offset from that timer base in monotonic time; and the next elapsation point on theCLOCK_MONOTONICclock, relative to its epoch ๐ฐ๏ธTimersCalendarโ an array of structs holding info about all the realtime/calendar timers on this timer unit. each struct has: a string naming the timer base, which for now may only be"OnCalendar"; the calendar specification string; and the next elapsation point on theCLOCK_REALTIMEclock, relative to its epoch ๐NextElapseUSecRealtimeโ the next elapsation point on theCLOCK_REALTIMEclock, in microseconds since the epoch. or0if this timer event doesn't include at least one calendar event ๐NextElapseUSecMonotonicโ same energy, but for theCLOCK_MONOTONICclock: the next elapsation point in microseconds since the epoch, or0if this timer event doesn't include at least one monotonic event.Resultโ knows the values"success"and"resources", with the same meanings as the matching values of the corresponding property on the service interface.
๐ SWAP UNIT OBJECTS ๐
every swap unit object implements the org.freedesktop.systemd1.Swap interface (described here) in addition to the generic org.freedesktop.systemd1.Unit interface (see above). two interfaces, one icon ๐
...and here we go, straight into the properties block, bestie. Buckle up, this is the part where systemd shows you everything it knows about your swap unit's cgroup. ๐
node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
interface org.freedesktop.systemd1.Swap {
methods:
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
properties:
readonly s What = '...';
readonly i Priority = ...;
readonly s Options = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutUSec = ...;
readonly u ControlPID = ...;
readonly s Result = '...';
readonly u UID = ...;
readonly u GID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecActivate = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("invalidates")
readonly a(sasbttttuii) ExecDeactivate = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
okay so let's actually read this thing, because it's giving โจ lore drop โจ.
๐ฆ the swap node itself
node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswapโ this is the D-Bus object that is your swap unit, hanging off the manager. It's aninterface org.freedesktop.systemd1.Swapliving inside it. Very "I have my own address on the bus" of it. ๐
๐ the methods
GetProcesses(out a(sus) processes);โ hand over the processes, shaped asa(sus).AttachProcesses(in s subcgroup, in au pids);โ takes asubcgroupstring and an array ofpids(au) and attaches them. Note the cute lil double-space afterinโ that's alignment, bestie, respect the craft.RemoveSubgroup(in s subcgroup, in t flags);โ takes asubcgroupandflags(at, i.e. the 64-bit unsigned type) and removes it.
๐ the properties, in the order they showed up
First the ones without an EmitsChangedSignal annotation, just raw readonly energy:
What(s) โ'...'Priority(i) โ...Options(s) โ'...'TimeoutUSec(t) โ and this one is tagged@org.freedesktop.DBus.Property.EmitsChangedSignal("const"). Only one here withconst, so obviously it thinks it's special. ๐ControlPID(u) โ...Result(s) โ'...'UID(u) โ...GID(u) โ...ExecActivate(a(sasbttttuii)) โ[...], taggedinvalidates.ExecDeactivate(a(sasbttttuii)) โ[...], also taggedinvalidates. Those two are the onlyinvalidatesgirlies in this whole block, everyone else got"false". ๐ซถ
And then โ every. single. remaining. property. tagged @org.freedesktop.DBus.Property.EmitsChangedSignal("false"). No skips. No shortcuts. Here's the full roll call:
Slice(s)'...'ControlGroup(s)'...'ControlGroupId(t)...MemoryCurrent(t)...MemoryPeak(t)...MemorySwapCurrent(t)...MemorySwapPeak(t)...MemoryZSwapCurrent(t)...MemoryAvailable(t)...EffectiveMemoryMax(t)...EffectiveMemoryHigh(t)...CPUUsageNSec(t)...EffectiveCPUs(ay)[...]EffectiveMemoryNodes(ay)[...]TasksCurrent(t)...EffectiveTasksMax(t)...IPIngressBytes(t)...IPIngressPackets(t)...IPEgressBytes(t)...IPEgressPackets(t)...IOReadBytes(t)...IOReadOperations(t)...IOWriteBytes(t)...IOWriteOperations(t)...OOMKills(t)...ManagedOOMKills(t)...Delegate(b)...DelegateControllers(as)['...', ...]DelegateSubgroup(s)'...'CPUWeight(t)...StartupCPUWeight(t)...CPUQuotaPerSecUSec(t)...CPUQuotaPeriodUSec(t)...AllowedCPUs(ay)[...]StartupAllowedCPUs(ay)[...]AllowedMemoryNodes(ay)[...]StartupAllowedMemoryNodes(ay)[...]CPUSetPartition(s)'...'IOAccounting(b)...IOWeight(t)...StartupIOWeight(t)...IODeviceWeight(a(st))[...]IOReadBandwidthMax(a(st))[...]IOWriteBandwidthMax(a(st))[...]IOReadIOPSMax(a(st))[...]IOWriteIOPSMax(a(st))[...]IODeviceLatencyTargetUSec(a(st))[...]MemoryAccounting(b)...MemoryMin(t)...MemoryLow(t)...StartupMemoryLow(t)...MemoryHigh(t)...StartupMemoryHigh(t)...MemoryMax(t)...StartupMemoryMax(t)...MemorySwapMax(t)...StartupMemorySwapMax(t)...MemoryZSwapMax(t)...StartupMemoryZSwapMax(t)...MemoryZSwapWriteback(b)...DevicePolicy(s)'...'DeviceAllow(a(ss))[...]TasksAccounting(b)...TasksMax(t)...IPAccounting(b)...IPAddressAllow(a(iayu))[...]IPAddressDeny(a(iayu))[...]IPIngressFilterPath(as)['...', ...]IPEgressFilterPath(as)['...', ...]DisableControllers(as)['...', ...]ManagedOOMSwap(s)'...'ManagedOOMMemoryPressure(s)'...'ManagedOOMMemoryPressureLimit(u)...ManagedOOMMemoryPressureDurationUSec(t)...ManagedOOMPreference(s)'...'OOMRules(as)['...', ...]BPFProgram(a(ss))[...]SocketBindAllow(a(iiqq))[...]SocketBindDeny(a(iiqq))[...]RestrictNetworkInterfaces((bas))...BindNetworkInterface(s)'...'MemoryPressureWatch(s)'...'MemoryPressureThresholdUSec(t)...
and then the very last line is a dangling @org.freedesktop.DBus.Property.EmitsChangedSignal("false") with nothing after it yet... ๐ which is our cue that this cgroup-property saga is not over, bestie. lowkey cliffhanger. keep scrolling. ๐ฅ
okay bestie we're still deep in the D-Bus property listing and it's giving infinite scroll ๐ญ grab a strawberry, we're going in ๐
first up: the pressure watch girlies, the NFT set, and a little coredump-receiving moment ๐
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
not me spotting those annotation lines riding along with every single property ๐ they're part of the listing, they're always there, they never leave. iconic consistency honestly.
and now the environment block, where the vibes are strictly "const" โ every single one of these is tagged that way, no exceptions, no notes โจ
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as Environment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sb) EnvironmentFiles = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as PassEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as UnsetEnvironment = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u UMask = ...;
Environment, EnvironmentFiles, PassEnvironment, UnsetEnvironment, UMask โ the whole environment-and-permissions friend group, all matching, all cute, all "const" ๐
okay this next chunk is the LONG one. it's the resource-limit section and bestie it does not stop. 32 properties, each with its own annotation above it, and every single one is typed t. hydrate. ๐ง
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPU = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCPUSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitFSIZESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitDATASoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSTACKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitCORESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRSSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNOFILESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitAS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitASSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNPROCSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCK = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMEMLOCKSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitLOCKSSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDING = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitSIGPENDINGSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitMSGQUEUESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitNICESoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIO = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTPRIOSoft = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIME = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LimitRTTIMESoft = ...;
the way that literally every hard limit has a ...Soft twin right after it?? it's giving matched set, it's giving โจ symmetry โจ, it's giving hard-limit-and-soft-limit-besties ๐ซถ and they're ALL "const" obviously, because of course they are.
okay phew, we survived. now: filesystem-and-rooting era ๐ธ working directories, root images, hashes, signatures, verity, ephemeral roots, extensions, mount images โ the whole rooted aesthetic:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s WorkingDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootDirectory = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImage = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) RootImageOptions = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHash = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay RootHashSignature = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootHashSignaturePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootVerity = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RootEphemeral = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootMStack = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExtensionDirectories = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sba(ss)) ExtensionImages = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssba(ss)) MountImages = [...];
look at those type signatures โ a(sba(ss)) and a(ssba(ss)) are genuinely doing the most and honestly? they ate ๐ฅ nested-struct realness, no cap. and yup, "const" all the way down, as always ๐
now the scheduling-and-vibes department: OOM score, coredump filter, niceness, IO scheduling, CPU scheduling, affinity, NUMA, timer slack, non-blocking. very "main character running a tight ship" energy ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i OOMScoreAdjust = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CoredumpFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i Nice = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingClass = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i IOSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i CPUSchedulingPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay CPUAffinity = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUAffinityFromNUMA = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i NUMAPolicy = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay NUMAMask = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimerSlackNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CPUSchedulingResetOnFork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NonBlocking = ...;
the range of types here is sending me โ i, t, ay, b โ a whole alphabet moment ๐ and yes bestie, every one is "const". we been knew.
standard input, standard output, standard error, and the TTY girls ๐ your three fave file descriptors plus their whole console situation:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardInputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly ay StandardInputData = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutput = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardOutputFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardError = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s StandardErrorFileDescriptorName = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s TTYPath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYReset = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVHangup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b TTYVTDisallocate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYRows = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly q TTYColumns = ...;
TTYRows and TTYColumns are typed q which is lowkey the cutest little type letter, and I will not be elaborating ๐
and finally the logging corner, where the syslog girlies live with the log level, the rate limit, the extra fields and the filter patterns ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogPriority = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s SyslogIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SyslogLevelPrefix = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogLevel = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SyslogFacility = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i LogLevelMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t LogRateLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogRateLimitBurst = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly aay LogExtraFields = [[...], ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(bs) LogFilterPatterns = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
LogExtraFields is aay with [[...], ...] โ an array of arrays of bytes, double-nested, doing the absolute most, and I'm obsessed ๐ and look, the chunk ends on a lone "const" annotation just hanging there with no property after it โ which means the next property is coming in the next part bestie, so hold that thought ๐
okay so we're still deep in the SERVICE unit property list, bestie โ this is the sandbox-and-security chunk and it is long, but every single one of these is a D-Bus property you can read back, and they all got EmitsChangedSignal("const") on them, which means โจ they never change at runtime โจ so don't be out here waiting for a signal that's never coming. Let's go group by group. ๐ซถ
namespaces, caps, and secure bits ๐
who even are you, security-wise:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s LogNamespace = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SecureBits = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t CapabilityBoundingSet = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t AmbientCapabilities = ...;
the whole identity crisis section ๐
user, group, dynamic user, login env, IPC cleanup:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s User = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Group = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b DynamicUser = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SetLoginEnvironment = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RemoveIPC = ...;
credentials, the secret handshake ๐
all the ways a unit gets handed its lil secrets โ set 'em, set 'em encrypted, load 'em, load 'em encrypted, import 'em, import 'em extended:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(say) SetCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredential = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) LoadCredentialEncrypted = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ImportCredential = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) ImportCredentialEx = [...];
groups & PAM ๐ธ
extra groups and the PAM service name, iconic:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SupplementaryGroups = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PAMName = '...';
paths: rw, ro, nope, exec, no-exec ๐ฆ
where the unit may write, where it may only read, where it may not even look, where it's allowed to exec from, and where it absolutely is not โ plus the mount flags. periodt.
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadWritePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ReadOnlyPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as InaccessiblePaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as NoExecPaths = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ExecSearchPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t MountFlags = ...;
the big ol' Private & Protect wall ๐งฑ
okay bestie this is the main character block. every Privateโฆ and every Protectโฆ lives here, and there's a bunch of โฆEx variants too. no skipping, no cap:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateTmp = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateTmpEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateDevices = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectClock = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelTunables = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelModules = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectKernelLogs = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectControlGroups = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectControlGroupsEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateNetwork = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateUsers = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateUsersEx = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateMounts = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b PrivateIPC = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivatePIDs = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectHome = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectSystem = '...';
process group & utmp stuff ๐
sharing a process group, plus how it shows up in the utmp/wtmp records:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SameProcessGroup = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpIdentifier = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UtmpMode = '...';
MAC labels (the security-module trio) ๐
SELinux, AppArmor, Smack โ all three of 'em, all (bs) tuples:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SELinuxContext = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) AppArmorProfile = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bs) SmackProcessLabel = ...;
a couple of lil b's ๐
SIGPIPE and privilege escalation, both just booleans:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b IgnoreSIGPIPE = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b NoNewPrivileges = ...;
syscall filtering ๐ฏ
the seccomp situation โ the filter itself, the architectures, the errno to return, and what gets logged:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallFilter = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as SystemCallArchitectures = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i SystemCallErrorNumber = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) SystemCallLog = ...;
personality โจ
the personality setting and whether it's locked down:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Personality = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LockPersonality = ...;
address families ๐
which socket families are allowed, as a (bas) tuple:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictAddressFamilies = ...;
the directories saga ๐
runtime, state, cache, logs, config โ each one gets a symlink list, a mode, sometimes accounting and quota, and the plain name list. it's giving organized. ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) RuntimeDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RuntimeDirectoryPreserve = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u RuntimeDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as RuntimeDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) StateDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as ConfigurationDirectory = ['...', ...];
note: config directories only get a mode and a name list โ no symlink list, no accounting, no quota. that's just how it is, bestie. ๐
timeouts, memory, realtime, namespaces, filesystems ๐ฅ
the cleanup timeout, W^X enforcement, realtime restriction, setuid/setgid restriction, namespace restriction, namespace delegation, and filesystem restriction:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutCleanUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryDenyWriteExecute = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictRealtime = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b RestrictSUIDSGID = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RestrictNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t DelegateNamespaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (bas) RestrictFileSystems = ...;
bind mounts & tmpfs ๐ช
bind mounts (rw and ro), temporary filesystems, whether to mount the API VFS, and whether to bind log sockets:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ssbt) BindReadOnlyPaths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) TemporaryFileSystem = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MountAPIVFS = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b BindLogSockets = ...;
keyring & /proc ๐๏ธ
the keyring mode, plus the two /proc knobs โ ProtectProc and ProcSubset:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KeyringMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProtectProc = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ProcSubset = '...';
and that's the whole security-and-sandbox property spread, bestie โ every one readonly, every one const, every one exactly what you asked for. more coming, don't go anywhere ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b ProtectHostname = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (ss) ProtectHostnameEx = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s PrivateBPF = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateCommands = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateMaps = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegatePrograms = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BPFDelegateAttachments = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MemoryKSM = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MemoryTHP = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s UserNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s NetworkNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s IPCNamespacePath = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s RootImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i KillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i RestartKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGKILL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGHUP = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i WatchdogSignal = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
โจ Properties โจ
okay so most of these properties just map straight onto the matching settings in your swap unit files, no plot twist ๐.
But here's the cute lil detail: swap units literally invoke the swapon(8) command, so their bus objects come with implicit ExecActivate (and similar) fields baked in โ those hold the info about which processes get executed. ๐ซถ
They also share most of the execution-context fields that Service objects expose (scroll up bestie, they're right there ๐).
And on top of all that, you also get these:
ControlPIDโ holds the PID of the currently runningswapon(8)orswapoff(8)command if one's actually running. If nothing's running? It's0. simple as that ๐Resultโ the lil explanation of why a mount unit failed, if it failed. It can be"success","resources","timeout","exit-code","signal", or"core-dump"โ and those have the identical meanings as the corresponding values of the corresponding field of service unit objects (again, see above ๐).
๐ฆ PATH UNIT OBJECTS ๐ฆ
node /org/freedesktop/systemd1/unit/cups_2epath {
interface org.freedesktop.systemd1.Path {
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Unit = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) Paths = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b MakeDirectory = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u DirectoryMode = ...;
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TriggerLimitIntervalUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u TriggerLimitBurst = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
โจ Properties โจ
fr fr, most of these properties correspond directly with the matching settings in path unit files. no notes. ๐ธ
Now the others:
Pathsโ this one's an array of structs ๐. Each struct holds two things: the condition to watch, and the path to watch (which can totally include glob expressions โจ).
The condition can be one of "PathExists", "PathExistsGlob", "PathChanged", "PathModified", or "DirectoryNotEmpty" โ and those correspond directly to the matching settings in the path unit files. iykyk ๐
Resultโ a result value that can be either"success"or"resources", and these have the same meaning as the corresponding field of theServiceinterface. ๐
๐ SLICE UNIT OBJECTS ๐
Okay bestie, listen up: all slice unit objects implement the org.freedesktop.systemd1.Slice interface (described right here, like literally in this bit ๐) in addition to the generic org.freedesktop.systemd1.Unit interface (see above ๐).
okay so this is the part where we actually open up a slice and look at its D-Bus glow-up ๐ like, the object path, the interface, the methods, the entire property roster. it's giving "backstage pass to the cgroup". let's go.
node /org/freedesktop/systemd1/unit/system_2eslice {
interface org.freedesktop.systemd1.Slice {
methods:
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
so the node lives at /org/freedesktop/systemd1/unit/system_2eslice โ that _2e is just an escaped ., bestie, don't panic ๐ซถ โ and the interface hanging off it is org.freedesktop.systemd1.Slice. three methods on deck:
GetProcesses(out a(sus) processes)โ hands you back an array of structs, each one a(string, uint32, string)triple. no args in, just vibes out.AttachProcesses(in s subcgroup, in au pids)โ you give it a subcgroup string and an array of uint32 PIDs (au= array of unsigned 32-bit).RemoveSubgroup(in s subcgroup, in t flags)โ subcgroup string plus at(that's a 64-bit unsigned, the chunky one) of flags.
now the properties โจ and listen, every single one of them is stamped with:
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
which is the annotation that says "don't sit around waiting for a change signal on this one" ๐ it's on all of them. every. single. one. so I'm not gonna re-read it 90 times, but it is genuinely there on each property, no cap.
โจ the concurrency girls โจ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ConcurrencyHardMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ConcurrencySoftMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ActivatingConcurrencyMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u NCurrentlyActive = ...;
four us (32-bit unsigned) all readonly, all ... for the value, because the actual number is a runtime thing, not a spec thing. ConcurrencyHardMax, ConcurrencySoftMax, ActivatingConcurrencyMax, NCurrentlyActive. iconic lineup tbh ๐
๐ธ where it sits in the world ๐ธ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
strings get quoted '...', numbers get bare .... Slice and ControlGroup are s, ControlGroupId is a t. and yes ControlGroupId is readonly t โ 64-bit, big girl numbers.
๐ฆ memory, but the live numbers ๐ฆ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
eight ts. current, peak, swap current, swap peak, zswap current, available, and then the two effective ones โ EffectiveMemoryMax and EffectiveMemoryHigh. note the word effective, bestie, that's the computed one, not the one you typed in the config ๐
๐ cpu + placement tea ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
CPUUsageNSec is a plain t. then EffectiveCPUs and EffectiveMemoryNodes are ay โ arrays of bytes, shown as [...] โ that's a bitmask situation, not a list of numbers you can just eyeball ๐ญ
๐ tasks + network + io counters ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMKills = ...;
counters counters counters. tasks current + effective max, four IP counters (ingress/egress ร bytes/packets), four IO counters (read/write ร bytes/operations), and the two OOM tallies โ OOMKills and ManagedOOMKills. all t, all readonly, all vibing ๐
๐ง delegation era ๐ง
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
Delegate is a b โ boolean, true/false energy. DelegateControllers is an as โ array of strings, and the sample is ['...', ...] so it's showing "one or more of these". DelegateSubgroup is a single s. cute. concise. obsessed.
๐ฅ cpu weight + quota + affinity ๐ฅ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
weights, then both flavours of the quota (PerSecUSec and PeriodUSec), then the four ay bitmask arrays โ and notice StartupAllowedCPUs and StartupAllowedMemoryNodes are the startup twins ๐ฏ plus CPUSetPartition as a lone s at the end, standing there, serving.
๐ io, the full spread ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
IOAccounting is a b, IOWeight and StartupIOWeight are ts, and then six a(st) arrays โ that's array-of-struct where each struct is (string, uint64), i.e. a device path paired with a number. IODeviceWeight, IOReadBandwidthMax, IOWriteBandwidthMax, IOReadIOPSMax, IOWriteIOPSMax, IODeviceLatencyTargetUSec. six of them. ate ๐
๐ memory settings, the whole alphabet ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
this is the big one, okay. MemoryAccounting = b. then MemoryMin, MemoryLow, StartupMemoryLow, MemoryHigh, StartupMemoryHigh, MemoryMax, StartupMemoryMax, MemorySwapMax, StartupMemorySwapMax, MemoryZSwapMax, StartupMemoryZSwapMax โ all t, and the startup twins are right there beside their originals ๐ซถ โ and then MemoryZSwapWriteback rounds it off as a b. periodt.
โญ devices + tasks + ip filtering โญ
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
DevicePolicy is a single s, DeviceAllow is a(ss) โ array of string-pairs. TasksAccounting = b, TasksMax = t. IPAccounting = b, and then IPAddressAllow / IPAddressDeny are a(iayu) โ array of structs of (int32, byte-array, uint32). then two as string arrays: IPIngressFilterPath and IPEgressFilterPath. okayyy ๐ธ
๐ controllers + oom management ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
DisableControllers = as. then the managed-OOM crew: ManagedOOMSwap (s), ManagedOOMMemoryPressure (s), ManagedOOMMemoryPressureLimit (u), ManagedOOMMemoryPressureDurationUSec (t โ note the USec, it's microseconds, don't get got), ManagedOOMPreference (s), and OOMRules (as). the whole family is here ๐ญ
๐ bpf, sockets, network interfaces ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
BPFProgram is a(ss). SocketBindAllow and SocketBindDeny are a(iiqq) โ array of structs of (int32, int32, uint16, uint16). RestrictNetworkInterfaces is a plain struct (bas) = (bool, array-of-strings) โ not an array, just one struct, keep it straight bestie. and BindNetworkInterface is a lone s.
๐ pressure watch, the finale of this part ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
four left and they're a tidy little pattern: a s watch setting and a t microsecond threshold, once for Memory and once for CPU. MemoryPressureWatch, MemoryPressureThresholdUSec, CPUPressureWatch, CPUPressureThresholdUSec. clean. symmetrical. we love a consistent queen โจ
and that's where this chunk cuts off โ the node's still open, the braces haven't closed, we're literally mid-object ๐ญ hold on to your seats, the rest is coming ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
and that's the whole interface, closed out, bow on top ๐ like yes we did just read every single property together and we're still standing
โจ Properties โจ
okay so the tea on these: most of them just mirror the matching settings in slice unit files. like, you know how you write a setting in the unit file? boom, there's a property with basically the same job. no cap, it's giving "the file and the bus are the same person wearing different outfits" ๐
One lil glow-up exception tho: ManagedOOMMemoryPressureDurationUSec is the one that implements the destination parameter of the unit file setting ManagedOOMMemoryPressureDurationSec= that's listed over in systemd.resource-control(5). ๐
โ ๏ธ heads up bestie: notice the time unit here is expressed in "ฮผs". that's microseconds, not seconds. the name switches fromSectoUSecfor a reason and the property is literally spelled with thatUโ don't come for me, that's just what it says ๐ญ๐
โจ SCOPE UNIT OBJECTS โจ
so, scope units. every single scope unit object implements the org.freedesktop.systemd1.Scope interface โ which is the one described right here, yes, this exact section, hi hello welcome ๐ซถ โ plus the generic org.freedesktop.systemd1.Unit interface, which is the one we went over way up above ๐
so like. two interfaces. one object. it's giving layered outfit, it's giving main character with a supporting cast, and honestly? iconic. ๐โจ
...and here's where it gets real โ this is the actual D-Bus shape of a scope unit, live from the bus. Bestie, this is the โจreceiptsโจ part. Every property, every annotation, exactly as it appears on the wire ๐
node /org/freedesktop/systemd1/unit/session_2d1_2escope {
interface org.freedesktop.systemd1.Scope {
methods:
Abandon();
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
RemoveSubgroup(in s subcgroup,
in t flags);
signals:
RequestStop();
properties:
readonly s Controller = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t TimeoutStopUSec = ...;
readonly s Result = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeMaxUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly t RuntimeRandomizedExtraUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s OOMPolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ControlGroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ControlGroupId = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapPeak = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryAvailable = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUUsageNSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay EffectiveMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksCurrent = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t EffectiveTasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPIngressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IPEgressPackets = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOReadOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteBytes = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWriteOperations = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t OOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMKills = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b Delegate = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DelegateControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DelegateSubgroup = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupCPUWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPerSecUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUQuotaPeriodUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedCPUs = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay AllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly ay StartupAllowedMemoryNodes = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUSetPartition = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IOAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupIOWeight = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceWeight = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteBandwidthMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOReadIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IOWriteIOPSMax = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(st) IODeviceLatencyTargetUSec = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMin = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryLow = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryHigh = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemorySwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t StartupMemoryZSwapMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b MemoryZSwapWriteback = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s DevicePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) DeviceAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b TasksAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t TasksMax = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b IPAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iayu) IPAddressDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPIngressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as IPEgressFilterPath = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as DisableControllers = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMSwap = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMMemoryPressure = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly u ManagedOOMMemoryPressureLimit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t ManagedOOMMemoryPressureDurationUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s ManagedOOMPreference = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly as OOMRules = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(ss) BPFProgram = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindAllow = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiqq) SocketBindDeny = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (bas) RestrictNetworkInterfaces = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s BindNetworkInterface = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s MemoryPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t MemoryPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s CPUPressureWatch = '...';
So what are we even looking at, bestie? This is one node on the system bus. The path /org/freedesktop/systemd1/unit/session_2d1_2escope is the escaped name of a scope unit โ _2d is a - and _2e is a ., that's the D-Bus escaping doing its little magic so the name can live in a path ๐
. Inside it sits the interface org.freedesktop.systemd1.Scope, and that's where all the tea is.
The methods, aka the buttons you can press ๐
Abandon()โ takes nothing in, gives nothing back. Zero args, zero return, just vibes.GetProcesses(out a(sus) processes)โ no inputs, but it hands you backprocesses, an array of structs shaped(s, u, s).AttachProcesses(in s subcgroup, in au pids)โ takessubcgroup(a string) andpids(an array of unsigned 32-bit ints). No return.RemoveSubgroup(in s subcgroup, in t flags)โ takessubcgroup(string) andflags(a 64-bit unsigned int). No return.
The signal ๐ฆ
RequestStop()โ no arguments, no return, just a signal showing up in your subscription like a little tap on the shoulder.
The properties ๐
Quick key before we dive, because the annotations are doing a lot of heavy lifting here:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")โ this one isconst, it doesn't change.@org.freedesktop.DBus.Property.EmitsChangedSignal("false")โ no change signal gets emitted for it.
And the type letters, since I know you're gonna ask: s is a string, b is a boolean, t is a 64-bit unsigned integer, u is a 32-bit unsigned integer, ay is an array of bytes, as is an array of strings, and the ones in parens like a(st) are arrays of structs.
Identity and lifecycle era โจ
Controllerโ types, and no annotation at all on this one.TimeoutStopUSecโ typet, markedconst.Resultโ types, no annotation.RuntimeMaxUSecโ typet, markedconst.RuntimeRandomizedExtraUSecโ typet, markedconst.OOMPolicyโ types, markedconst.
cgroup + live accounting (all of these are false, so no change signals, bestie) ๐
Sliceโ types.ControlGroupโ types.ControlGroupIdโ typet.MemoryCurrentโ typet.MemoryPeakโ typet.MemorySwapCurrentโ typet.MemorySwapPeakโ typet.MemoryZSwapCurrentโ typet.MemoryAvailableโ typet.EffectiveMemoryMaxโ typet.EffectiveMemoryHighโ typet.CPUUsageNSecโ typet.EffectiveCPUsโ typeay, an array of bytes.EffectiveMemoryNodesโ typeay, an array of bytes.TasksCurrentโ typet.EffectiveTasksMaxโ typet.IPIngressBytesโ typet.IPIngressPacketsโ typet.IPEgressBytesโ typet.IPEgressPacketsโ typet.IOReadBytesโ typet.IOReadOperationsโ typet.IOWriteBytesโ typet.IOWriteOperationsโ typet.OOMKillsโ typet.ManagedOOMKillsโ typet.
Delegation corner ๐ซถ
Delegateโ typeb, a boolean.DelegateControllersโ typeas, an array of strings.DelegateSubgroupโ types.
CPU settings, the whole set โญ
CPUWeightโ typet.StartupCPUWeightโ typet.CPUQuotaPerSecUSecโ typet.CPUQuotaPeriodUSecโ typet.AllowedCPUsโ typeay.StartupAllowedCPUsโ typeay.AllowedMemoryNodesโ typeay.StartupAllowedMemoryNodesโ typeay.CPUSetPartitionโ types.
IO settings, she's thorough ๐
IOAccountingโ typeb.IOWeightโ typet.StartupIOWeightโ typet.IODeviceWeightโ typea(st), an array of(string, uint64)structs.IOReadBandwidthMaxโ typea(st).IOWriteBandwidthMaxโ typea(st).IOReadIOPSMaxโ typea(st).IOWriteIOPSMaxโ typea(st).IODeviceLatencyTargetUSecโ typea(st).
Memory settings, and yes there are a LOT ๐ธ
MemoryAccountingโ typeb.MemoryMinโ typet.MemoryLowโ typet.StartupMemoryLowโ typet.MemoryHighโ typet.StartupMemoryHighโ typet.MemoryMaxโ typet.StartupMemoryMaxโ typet.MemorySwapMaxโ typet.StartupMemorySwapMaxโ typet.MemoryZSwapMaxโ typet.StartupMemoryZSwapMaxโ typet.MemoryZSwapWritebackโ typeb.
Devices + tasks ๐
DevicePolicyโ types.DeviceAllowโ typea(ss), an array of(string, string)structs.TasksAccountingโ typeb.TasksMaxโ typet.
Network, IP and OOM behaviour ๐ฅ
IPAccountingโ typeb.IPAddressAllowโ typea(iayu), an array of(int32, array of bytes, uint32)structs.IPAddressDenyโ typea(iayu).IPIngressFilterPathโ typeas.IPEgressFilterPathโ typeas.DisableControllersโ typeas.ManagedOOMSwapโ types.ManagedOOMMemoryPressureโ types.ManagedOOMMemoryPressureLimitโ typeu, a 32-bit unsigned int.ManagedOOMMemoryPressureDurationUSecโ typet.ManagedOOMPreferenceโ types.OOMRulesโ typeas.
Sandboxing + pressure watch, the final stretch ๐
BPFProgramโ typea(ss), an array of(string, string)structs.SocketBindAllowโ typea(iiqq), an array of(int32, int32, int16, int16)structs.SocketBindDenyโ typea(iiqq).RestrictNetworkInterfacesโ type(bas), a single struct of(boolean, array of strings).BindNetworkInterfaceโ types.MemoryPressureWatchโ types.MemoryPressureThresholdUSecโ typet.CPUPressureWatchโ types.
That's the whole interface, no skips, no crumbs left behind ๐ and there's still more coming, so don't go anywhere ๐
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t CPUPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s IOPressureWatch = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly t IOPressureThresholdUSec = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly a(iiss) NFTSet = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly b CoredumpReceive = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i KillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i RestartKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i FinalKillSignal = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGKILL = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b SendSIGHUP = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly i WatchdogSignal = ...;
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
interface org.freedesktop.systemd1.Unit { ... };
};
okay so that's the tail end of the scope interface ๐ and now we get into the good stuff โ the methods and signals for scopes, bestie, let's GO โจ
Methods ๐ ๏ธ
Abandon()โ this one is iconic honestly. It lets you drop a scope unit into the "abandoned" state ๐ซถ. Basically you're telling the system manager "hey, the manager that made this scope? it lost interest, k? it's peacing out" โ like when it's terminating โ without actually wanting to shut the whole scope down. So the scope stays alive, you just stop being its problem. periodt ๐
Signals ๐ก
RequestStop()โ this gets sent to whoever is configured in theControllerproperty when systemd is asked to terminate the scope unit. And here's the slay part: a program that registered a scope can use this to cleanly shut down the processes it added to the scope, instead of just letting systemd come in and do it with the usualSIGTERMlogic ๐ญโจ. It's giving considerate. It's giving let me handle my own kids.
Properties ๐ท๏ธ
Lowkey the biggest vibe here: all properties correspond directly with the matching properties of service units. No new lore, same energy ๐.
Controllerโ holds the bus name (could be unique or well-known) that gets notified when the scope unit is about to be shut down, via thatRequestStop()signal we just talked about (see above โฌ๏ธ). This gets set when the scope is created. And if it's not set? Then the scope's processes get terminated withSIGTERMdirectly. No heads-up, just vibes and signals ๐ .ManagedOOMMemoryPressureDurationUSecโ this implements the destination parameter of the unit file settingManagedOOMMemoryPressureDurationSec=listed over insystemd.resource-control(5). And ngl, note that the time unit is expressed in "ฮผs" โ yes bestie, microseconds, don't come for me ๐ธ.
๐ JOB OBJECTS ๐
Okay so job objects?? They encapsulate scheduled or running jobs ๐. Real talk: each unit can have none or one jobs in the execution queue, and each job is attached to exactly one unit. One unit, one job, no sharing, we don't do situationships here ๐.
node /org/freedesktop/systemd1/job/666 {
interface org.freedesktop.systemd1.Job {
methods:
Cancel();
GetAfter(out a(usssoo) jobs);
GetBefore(out a(usssoo) jobs);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u Id = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (so) Unit = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s JobType = '...';
readonly s State = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(ss) ActivationDetails = [...];
};
interface org.freedesktop.DBus.Peer { ... };
interface org.freedesktop.DBus.Introspectable { ... };
interface org.freedesktop.DBus.Properties { ... };
};
Methods ๐ ๏ธ
Cancel()โ cancels the job, bestie ๐ . But lowkey important caveat: this will remove a job from the queue if it is not yet executed, but generally it will not cause a job that's already in the process of being executed to be aborted ๐ญ. So it's giving "you can cancel the plans but not the thing that's already happening." Also you can request this same operation via theCancelJob()method of the Manager object (see above โฌ๏ธ), which is sometimes useful to reduce roundtrips โ efficiency queen โจ.
Properties ๐ท๏ธ
Idโ the numeric Id of the job ๐ข. And here's the tea: during the runtime of a systemd instance, each numeric ID is only assigned once. No recycling, no repeats, each number is its own main character ๐.Unitโ refers to the unit this job belongs to. It's a structure consisting of the name of the unit and a bus path to the unit's object ๐ฆ.JobTypeโ the job's type, and it's one of "start", "verify-active", "stop", "reload", "restart", "try-restart", or "reload-or-start". And heads up: note that later versions might define additional values ๐ so don't hardcode your assumptions, k?Stateโ the job's state, and it's one of "waiting" and "running" ๐. The former means a job is currently queued but has not begun to execute yet (it's in its waiting era ๐). The latter means a job is currently being executed (it's booked and busy ๐ ).ActivationDetailsโ has the exact same content as the property of the same name under theorg.freedesktop.systemd1.Unitinterface. Same content, different day ๐.
โจ EXAMPLES โจ
Get you a manpage that SHOWS you instead of just telling you, fr fr ๐ซถ
Example 1. Introspect org.freedesktop.systemd1.Manager on the bus ๐
$ gdbus introspect --system \
--dest org.freedesktop.systemd1 \
--object-path /org/freedesktop/systemd1
Example 2. Introspect a unit on the bus ๐ฆ
$ busctl introspect org.freedesktop.systemd1 \
$(busctl call org.freedesktop.systemd1 \
/org/freedesktop/systemd1 \
org.freedesktop.systemd1.Manager \
GetUnit s systemd-resolved.service | cut -d'"' -f2)
Look at that nested command substitution, bestie ๐ญ it's giving I contain multitudes.
Example 3. Introspect org.freedesktop.systemd1.Job on the bus ๐ผ
$ gdbus introspect --system --dest org.freedesktop.systemd1 \
--object-path /org/freedesktop/systemd1/job/1292
๐ VERSIONING ๐
These D-Bus interfaces follow the usual interface versioning guidelines<sup>[4]</sup> โ yes, there's a footnote, and yes, it's real, go look it up iykyk ๐โจ.
๐ HISTORY ๐
This is the lore drop section. Grab a snack, we're going through everything that ever got added and when ๐
The Manager Object ๐
RuntimeWatchdogPreUSecandRuntimeWatchdogPreGovernorwere added in version 251.WatchdogDevice,WatchdogLastPingTimestamp,WatchdogLastPingTimestampMonotonic,DefaultDeviceTimeoutUSec,DumpUnitsMatchingPatterns(), andDumpUnitsMatchingPatternsByFileDescriptor()were added in version 252.GetUnitByPIDFD()andDisableUnitFilesWithFlagsAndInstallInfo()were added in version 253.ConfidentialVirtualization,DefaultIOAccounting,DefaultIPAccounting,DefaultMemoryPressureThresholdUSec,DefaultMemoryPressureWatch,QueueSignalUnit(),SoftReboot(), andDumpUnitFileDescriptorStore()were added in version 254.StartAuxiliaryScope()was added in version 256, deprecated in version 257, removed in version 258. RIP bozo, we barely knew ye ๐ (but fr, don't use it, it's gone).ShutdownStartTimestamp,ShutdownStartTimestampMonotonic, andSoftRebootsCountwere added in version 256.DefaultRestrictSUIDSGID,RemoveSubgroupFromUnit(), andKillUnitSubgroup()were added in version 258.TransactionsWithOrderingCyclewas added in version 259.DefaultMemoryZSwapWriteback,DefaultCPUPressureThresholdUSec,DefaultCPUPressureWatch,DefaultIOPressureThresholdUSec,DefaultIOPressureWatch,ReloadCount,EventLoopRateLimitIntervalUSec, andEventLoopRateLimitBurstwere added in version 261.KExecCount,EnqueueUnitJobMany(),ShutdownFinishTimestamp,ShutdownFinishTimestampMonotonic,PreviousShutdownStartTimestamp,PreviousShutdownStartTimestampMonotonic,PreviousShutdownFinishTimestamp,PreviousShutdownFinishTimestampMonotonic,PreviousShutdownLateStartTimestamp,PreviousShutdownLateStartTimestampMonotonic,PreviousShutdownLateFinishTimestamp, andPreviousShutdownLateFinishTimestampMonotonicwere added in version 262. That's a whole paragraph of timestamps and I respect the commitment ๐ซถ.
Unit Objects ๐งฉ
UpholdsandUpheldBywere added in version 251.AccessSELinuxContextandActivationDetailswere added in version 252.QueueSignal()was added in version 254.SurviveFinalKillSignalwas added in version 255.WantsMountsForwas added in version 256.DebugInvocation, andCanLiveMountwere added in version 257.
Service Unit Objects ๐๏ธ
ControlGroupIdandExtensionDirectorieswere added in version 251.OpenFile,ReloadSignal,MemoryZSwapMax, andLogFilterPatternswere added in version 253.RestartMode,RestartSteps,RestartMaxDelayUSec,RestartUSecNext,FileDescriptorStorePreserve,DumpFileDescriptorStore(),DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch,MemoryPressureThresholdUSec,RootEphemeral,ImportCredential,MemoryKSM,RootImagePolicy,MountImagePolicy, andExtensionImagePolicywere added in version 254.NFTSet,SetLoginEnvironment,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255.EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax,MemoryZSwapWriteback,ExecMainHandoffTimestampMonotonic, andExecMainHandoffTimestampwere added in version 256.StatusBusError,StatusVarlinkError,LiveMountResult,PrivateTmpEx,ImportCredentialEx,ExtraFileDescriptorNames,ManagedOOMMemoryPressureDurationUSec,BindLogSockets,ProtectControlGroupsEx,PrivateUsersEx, andPrivatePIDswere added in version 257.ProtectHostnameEx,DelegateNamespaces,PrivateBPF,BPFDelegateCommands,BPFDelegateMaps,BPFDelegatePrograms,BPFDelegateAttachments,RemoveSubGroup(),StateDirectoryQuota,StateDirectoryQuotaUsage,StateDirectoryAccounting,CacheDirectoryQuota,CacheDirectoryQuotaUsage,CacheDirectoryAccounting,LogsDirectoryQuota,LogsDirectoryQuotaUsage,LogsDirectoryAccounting, andKillSubgroup()were added in version 258.UserNamespacePath,OOMKills,ManagedOOMKills,ExecReloadPost, andExecReloadPostExwere added in version 259.BindNetworkInterface,MemoryTHP,RefreshOnReload, andRootMStackwere added in version 260.CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261.LUOSessionwas added in version 262.RestartRandomizedDelayUSecwas added in version 262.
Socket Unit Objects ๐
ControlGroupIdandExtensionDirectorieswere added in version 251.MemoryZSwapMaxandLogFilterPatternswere added in version 253.DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch,MemoryPressureThresholdUSec,RootEphemeral,ImportCredential,MemoryKSM,RootImagePolicy,MountImagePolicy, andExtensionImagePolicywere added in version 254.PollLimitIntervalUSec,PollLimitBurst,NFTSet,SetLoginEnvironment,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255.EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax,MemoryZSwapWriteback, andPassFileDescriptorsToExecwere added in version 256.
okay bestie, picking the Device Unit Objects list right back up like nothing happened ๐ no cap, we're in the version-history trenches now and honestly? iconic behaviour from systemd.
- version 257 โ
PrivateTmpEx,ImportCredentialEx,BindLogSockets,PrivateUsersEx,ManagedOOMMemoryPressureDurationUSec,ProtectControlGroupsEx, andPrivatePIDswere added in version 257. - version 258 โ
ProtectHostnameEx,PassPIDFD,AcceptFileDescriptors,DelegateNamespaces,PrivateBPF,BPFDelegateCommands,BPFDelegateMaps,BPFDelegatePrograms,BPFDelegateAttachments,RemoveSubgroup(),DeferTrigger,DeferTriggerMaxUSec,StateDirectoryQuota,StateDirectoryQuotaUsage,StateDirectoryAccounting,CacheDirectoryQuota,CacheDirectoryQuotaUsage,CacheDirectoryAccounting,LogsDirectoryQuota,LogsDirectoryQuotaUsage,LogsDirectoryAccounting, andKillSubgroup()were added in version 258. - version 259 โ
UserNamespacePath,OOMKills, andManagedOOMKillswere added in 259. - version 260 โ
BindNetworkInterface,MemoryTHP, andRootMStackwere added in version 260. - version 261 โ
CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261. - version 262 โ
XAttrEntryPoint,XAttrListen, andXAttrAcceptwere added in version 262.
๐ Mount Unit Objects
- version 251 โ
ControlGroupIdandExtensionDirectorieswere added in version 251. - version 253 โ
MemoryZSwapMaxandLogFilterPatternswere added in version 253. - version 254 โ
DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch,MemoryPressureThresholdUSec,RootEphemeral,ImportCredential,MemoryKSM,RootImagePolicy,MountImagePolicy, andExtensionImagePolicywere added in version 254. - version 255 โ
NFTSet,SetLoginEnvironment,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255. - version 256 โ
EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax, andMemoryZSwapWritebackwere added in version 256. - version 257 โ
PrivateTmpEx,ImportCredentialEx,BindLogSockets,PrivateUsersEx,ManagedOOMMemoryPressureDurationUSec,ProtectControlGroupsEx, andPrivatePIDswere added in version 257. - version 258 โ
ProtectHostnameEx,DelegateNamespaces,PrivateBPF,BPFDelegateCommands,BPFDelegateMaps,BPFDelegatePrograms,BPFDelegateAttachments,RemoveSubgroup(),ReloadResult,CleanResult,StateDirectoryQuota,StateDirectoryQuotaUsage,StateDirectoryAccounting,CacheDirectoryQuota,CacheDirectoryQuotaUsage,CacheDirectoryAccounting,LogsDirectoryQuota,LogsDirectoryQuotaUsage,LogsDirectoryAccounting, andKillSubgroup()were added in version 258. - version 259 โ
UserNamespacePath,OOMKills, andManagedOOMKillswere added in 259. - version 260 โ
BindNetworkInterface,MemoryTHP, andRootMStackwere added in version 260. - version 261 โ
CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261.
๐ฆ Swap Unit Objects
- version 251 โ
ControlGroupIdandExtensionDirectorieswere added in version 251. - version 253 โ
MemoryZSwapMaxandLogFilterPatternswere added in version 253. - version 254 โ
DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch,MemoryPressureThresholdUSec,RootEphemeral,ImportCredential,MemoryKSM,RootImagePolicy,MountImagePolicy, andExtensionImagePolicywere added in version 254. - version 255 โ
NFTSet,SetLoginEnvironment,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255. - version 256 โ
EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax, andMemoryZSwapWritebackwere added in version 256. - version 257 โ
PrivateTmpEx,ImportCredentialEx,BindLogSockets,PrivateUsersEx,ManagedOOMMemoryPressureDurationUSec,ProtectControlGroupsEx, andPrivatePIDswere added in version 257. - version 258 โ
ProtectHostnameEx,DelegateNamespaces,PrivateBPF,BPFDelegateCommands,BPFDelegateMaps,BPFDelegatePrograms,BPFDelegateAttachments,RemoveSubgroup(),StateDirectoryQuota,StateDirectoryQuotaUsage,StateDirectoryAccounting,CacheDirectoryQuota,CacheDirectoryQuotaUsage,CacheDirectoryAccounting,LogsDirectoryQuota,LogsDirectoryQuotaUsage,LogsDirectoryAccounting, andKillSubgroup()were added in version 258. - version 259 โ
UserNamespacePath,OOMKills, andManagedOOMKillswere added in 259. - version 260 โ
BindNetworkInterface,MemoryTHP, andRootMStackwere added in version 260. - version 261 โ
CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261.
๐ Slice Unit Objects
- version 251 โ
ControlGroupIdwas added in version 251. - version 253 โ
MemoryZSwapMaxwas added in version 253. - version 254 โ
DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch, andMemoryPressureThresholdUSecwere added in version 254. - version 255 โ
NFTSet,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255. - version 256 โ
EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax, andMemoryZSwapWritebackwere added in version 256. - version 257 โ
ManagedOOMMemoryPressureDurationUSecwas added in version 257. - version 258 โ
ConcurrencyHardMax,ConcurrencySoftMax,NCurrentlyActive,RemoveSubgroup(), andKillSubgroup()were added in version 258. - version 259 โ
OOMKills, andManagedOOMKillswere added in 259. - version 260 โ
BindNetworkInterfacewas added in version 260. - version 261 โ
CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261. - version 262 โ
ActivatingConcurrencyMaxwas added in version 262.
๐ Scope Unit Objects
- version 251 โ
ControlGroupIdwas added in version 251. - version 253 โ
OOMPolicyandMemoryZSwapMaxwere added in version 253. - version 254 โ
DelegateSubgroup,DefaultStartupMemoryLow,StartupMemoryLow,StartupMemoryHigh,StartupMemoryMax,StartupMemorySwapMax,StartupMemoryZSwapMax,MemoryPressureWatch, andMemoryPressureThresholdUSecwere added in version 254. - version 255 โ
NFTSet,CoredumpReceive,MemoryPeak,MemorySwapCurrent,MemorySwapPeak, andMemoryZSwapCurrentwere added in version 255. - version 256 โ
EffectiveMemoryHigh,EffectiveMemoryMax,EffectiveTasksMax, andMemoryZSwapWritebackwere added in version 256. - version 257 โ
ManagedOOMMemoryPressureDurationUSecwas added in version 257. - version 258 โ
RemoveSubgroup()andKillSubgroup()were added in version 258. - version 259 โ
OOMKills, andManagedOOMKillswere added in 259. - version 260 โ
BindNetworkInterfacewas added in version 260. - version 261 โ
CPUPressureThresholdUSec,CPUPressureWatch,IOPressureThresholdUSec,IOPressureWatch,CPUSetPartition, andOOMRuleswere added in version 261.
โจ Job Objects โจ
- version 252 โ
ActivationDetailswas added in version 252.
๐ธ Timer Objects ๐ธ
- version 257 โ
DeferReactivationwas added in version 257. - version 258 โ
RandomizedOffsetUSecwas added in version 258.
๐ SEE ALSO ๐
like, go read your friends, bestie, they're literally right there ๐ซถ
๐ NOTES ๐
- polkit
https://www.freedesktop.org/software/polkit/docs/latest/ - New Control Group Interface
https://systemd.io/CONTROL_GROUP_INTERFACE - The Case for the /usr Merge
https://systemd.io/THE_CASE_FOR_THE_USR_MERGE - the usual interface versioning guidelines
https://0pointer.de/blog/projects/versioning-dbus.html
and that's the whole page, bestie โ every single option, every version bump, all of it ๐
that's a wrap on ORG.FREEDESKTOP.SYSTEMD1(5) fr fr โจ this one's the systemd 262.1 flavour, dated however your copy of the docs says it is โ go forth and systemctl responsibly, you ate that ๐๐๐ฆ
๐ฆ where this page comes from
- arch rolling: systemd 262.1-1 ยท LGPL-2.1-or-later AND CC0-1.0 AND GPL-2.0-or-later AND MIT-0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms