Saturday, March 15, 2025

systemctl is-enabled is strange

The is-enabled command of the systemd systemctl command is purported to:

Checks whether any of the specified unit files are enabled (as with enable). Returns an exit code of 0 if at least one is enabled, non-zero otherwise.

But read the documentation carefully because, in my opinion, it doesn't do this.

In particular, its exit code cannot be relied on to indicate if a unit is enabled.

The text output is more useful but to use this in automation requires capturing the text output and parsing it to determine whether the unit might be enabled.

But look at the table of text outputs. Look at 'static'. The documentation says:

The unit file is not enabled, and has no provisions for enabling in the [Install] unit file section.

But it also says that for such a unit the exit code of 'is-enabled' will be 0, indicating the unit is enabled.

This is inconsistent: is the unit enabled as indicated by the exit code? Or is it "not enabled, and has no provisions for enabling" as indicated by the specification of the text output "static"?

In my opinion, if the unit is not enabled then the exit code should be non-zero, to be consistent with the intent that a 0 exit code indicates an enabled unit.

Similarly for "indirect":

The unit file itself is not enabled, but it has a non-empty Also= setting in the [Install] unit file section, listing other unit files that might be enabled, or it has an alias under a different name through a symlink that is not specified in Also=. For template unit files, an instance different than the one specified in DefaultInstance= is enabled.

But again, despite "The unit file itself is not enabled", the exit code will be 0. So, is it enabled per the exit code or not enabled per the definition of the output message?

There are other cases with similar ambiguities. Some have descriptions that are so laden with esoteric systemd jargon that they are effectively meaningless to the ordinary reader, leaving it unknown if the unit is enabled and how it will behave in any particular circumstance.

And even parsing the text message is not always adequate to determine if a unit is enabled. Consider "symlink"

The name is an alias (symlink to another unit file).

So, regardless of whether that other unit file is enabled or not, the exit code will be 0 and the text message will be "symlink". That's not very helpful. In the case of a symlink, it will be necessary to follow the link and determine whether that linked unit is enabled or not: which is the purported purpose of the 'is-enabled' command - but it just doesn't bother to do it.

For some particular types of unit files (e.g. service units that are not symlinks, aliases, dynamic, etc.) then the exit code and output text both provide unambiguous indication of whether the unit is enabled, but for others, not so much.

So, check to be sure the unit you are checking is one of the types for which 'is-enabled' provides unambiguous, correct output, or write your own function that doesn't depend on the 'is-enabled' command.
 

No comments:

Labels