Open rgwood opened 11 months ago
Oof: https://github.com/coreos/go-systemd/issues/289#issuecomment-429283898
This exactly pinpoints what's confusing about it all: Knowing the logic for when a unit is loaded. You can do
systemctl status <unloaded unit>
, which will make systemd load the unit ad hoc for the purpose of displaying information about it. So it looks loaded in the terminal output, but is immediately un-loaded again by systemd.loaded but inactive units only matches "started" units.
So maybe there isn't a good way to show disabled services...
systemctl list-unit-files
seems like it can get disabled services, but... that kinda sucks, I guess I'd need to query DBus and run that.
Seems like there is a dbus function I can call: https://www.freedesktop.org/software/systemd/man/latest/systemd.directives.html#ListUnitFiles()
Will look into that.
OK, one problem with that function is that it's pretty slow. Takes about 100ms (user) + 300ms (global) on my 13th gen i7 (Ubuntu 24), I imagine it would be several seconds on slow machines.
I don't want that to block startup with that and I'm not sure I should run it too often. My current idea is to track this enabled/disabled/static/masked state as an Option
Semi-related, I think I like this way of thinking about systemd unit state as having 3 components:
1. boot behavior state:
• enabled/disabled/masked/static
2. runtime state:
• active/inactive/activating/deactivating/failed/exited/reloading
3. memory state:
• loaded/not-loaded
From a brainstorming session with 3.5 Sonnet, so take it with a grain of salt:
Prompt: systemd services have a lot of different states they can be in. explain the difference
between: enabled/disabled, active/inactive, loaded/not loaded
Assistant: alright, let's break this down:
enabled/disabled:
• refers to whether a service is set to start automatically on boot
• enabled: service will start on boot
• disabled: service won't start on boot
• this setting persists across reboots
• controlled via systemctl enable/disable
active/inactive:
• indicates the current running state of the service
• active: service is currently running
• inactive: service is not currently running
• this is a transient state and can change during system operation
• controlled via systemctl start/stop
loaded/not loaded:
• relates to whether systemd has parsed and loaded the service unit file into memory
• loaded: unit file is parsed and ready for use
• not loaded: unit file hasn't been read by systemd yet
• typically, services are loaded automatically when needed
• can be influenced by systemctl daemon-reload
it's worth noting that these states are not mutually exclusive. for example, a service can be
enabled (set to start on boot) but currently inactive (not running). or it could be loaded
(parsed by systemd) but disabled (won't start automatically).
the interplay between these states allows for fine-grained control over service behavior and
system resource management. afaik, this granularity is one of the key advantages of systemd over
traditional init systems.
Prompt: are there other common states I should add to my mental model?
Assistant: absolutely. to flesh out your mental model, consider these additional states:
failed:
• indicates a service that attempted to start but encountered an error
• often requires investigation of logs or configuration
masked:
• a stronger form of "disabled"
• prevents the service from being started manually or automatically
• useful for preventing conflicting services from running
static:
• service unit that cannot be enabled/disabled
• typically used for units that are dependencies of other units
exited:
• service that ran successfully and completed its task
• common for one-shot services that perform a single action
reloading:
• transitional state when a service is told to reload its configuration
activating/deactivating:
• transitional states when a service is starting up or shutting down
running:
• specific sub-state of "active" for continuously running services
dead:
• specific sub-state of "inactive" for services not running
plugged/mounted/waiting:
• states more relevant to device units or mount units
idk if all of these are critical for everyday use, but they can be valuable when troubleshooting
or when you need a more nuanced understanding of system behavior. the systemctl list-units --all
command can show you a wide array of these states in action.
remember, systemd's state model is quite GRANULAR, allowing for precise control and monitoring
of system services.
Prompt: is it reasonable to think of systemd units as having 3 separate states? e.g.
1. enabled/disabled/masked/etc.
2. active/inactive/activating/deactivating/etc.
3. loaded/not loaded
Assistant: that's a PERSPICACIOUS way of looking at it. your model is quite reasonable and can
be a useful mental framework. let's break it down:
1. boot behavior state:
• enabled/disabled/masked/static
2. runtime state:
• active/inactive/activating/deactivating/failed/exited/reloading
3. memory state:
• loaded/not-loaded
this tripartite model does capture the main aspects of a unit's lifecycle and configuration. it
separates:
1. how the unit behaves across reboots
2. what the unit is doing right now
3. whether systemd has the unit's configuration in memory
benefits of this model:
• it's easy to remember
• it covers most common scenarios
• it aligns well with how systemd actually manages units
caveats:
• some states (like "plugged" or "mounted") don't fit neatly
• it doesn't capture all nuances (e.g., sub-states of "active")
• some states can overlap or influence others
afaict, your model is a solid simplification that works well for most use cases. it's
particularly useful for understanding the basic lifecycle of a service:
1. is it set to run on boot?
2. is it running now?
3. has systemd loaded its configuration?
for day-to-day operations and basic troubleshooting, this mental model should serve you well. just
be aware that there's additional complexity if you need to dive deeper.
Prompt: ok, adjust that mental model to include things like plugged and mounted
Assistant: alright, let's refine that model to be more comprehensive. we can think of systemd
units as having these state categories:
1. boot behavior state:
• enabled/disabled/masked/static
2. runtime state:
• primary: active/inactive/activating/deactivating/failed
• sub-states: running/exited/dead/reloading
3. memory state:
• loaded/not-loaded
4. specialized states:
• for device units: plugged/unplugged
• for mount units: mounted/unmounted
• for path units: waiting/triggered
• for timer units: waiting/elapsed
this adjusted model now accounts for the specialized states that didn't fit neatly before. it
recognizes that different types of units can have unique states relevant to their function.
key points:
• categories 1-3 apply generally to all units
• category 4 is type-specific and may overlap with category 2
• some states (like "waiting") can have different meanings depending on the unit type
this model is more COMPREHENSIVE but still maintains a logical structure. it acknowledges that
while all units share some common states, there's also type-specific behavior to consider.
caveats:
• there's still some potential for overlap between categories
• it's more complex than the previous model, which might be overkill for basic usage
• it doesn't capture every possible state, but covers the most common ones
afaik, this refined model should give you a solid mental framework for understanding systemd
unit states across various unit types. it balances comprehensiveness with usability, though for
day-to-day operations, you might still find the simpler model sufficient.
Made some progress on this. Think I'm only going to show disabled and enabled services to start. Showing masked/static/generated services is super noisy and I don't think there's any benefit to it.
Right now we only show enabled services. Fix that, then add enable/disable actions.