0

I would like to be able to duplicate the list of enabled systemd units from one machine to another.

A systemd unit is enabled or disabled based on the existence (or lack) of a sym-link. At this time, the best tool I've been able to think of is tree or perhaps find? So, in theory, I could script something up; but isn't there already a tool to do this?

In a perfect world, it would scan all the various directories where such symlinks are created (I know of 3: /etc/systemd /run/systemd ~/.config/systemd/user) and render a readable file which could be used to replay the settings on another computer. Also useful for backup.

1
  • 1
    You may not actually want to save the state of units not explicitly enabled/disabled. Distribution maintainers do not specifically avoid breaking such use case in the way they design their post-upgrade scripts. If you have mismatching downstream distributions updates (or worse, systemd upstream releases), one of the systems might have enablement state inappropriate for the other as a result on ongoing version migrations.
    – anx
    Jun 2 at 19:50

2 Answers 2

2

To create a list of enabled systemd services we can use

ENABLED_SERVICES=$(systemctl list-unit-files | grep enabled | cut -d\  -f1)

This would leave us with the variable ENABLED_SERVICES with a list of enabled services, one per line.

To enable all services in this list, we can use

echo "${ENABLED_SERVICES}" | xargs -I{} systemctl enable {}

You'll probably want to review the commands before they're actually executed. You can do this by running

echo "${ENABLED_SERVICES}" | xargs -I{} echo systemctl enable {}

(watch out for the additional echo statement).

The only thing that is left, is to get the variable ENABLED_SERVICES from system A to system B, so that they can be used to enable the services there. There are several options to do this. For example you can redirect the output of the first command to a file, transfer it to system B and assign the output of the cat command from this file to a variable with the name ENABLED_SERVICES.

However, it might be simpler to use a modified version of the first command

echo -n "ENABLED_SERVICES=\""; systemctl list-unit-files | grep enabled | cut -d\  -f1; echo -n "\"";

and copy the output and paste it into a terminal on system B. This command produces multiple lines of output, which is perfectly fine.

1
  • Slight issue with the above: there are 2 columns of enabled/disabled the first is the current state and the 2nd is the preset. We want to skip any "enabled" presets with "disabled" state; so copying your idea, this works: systemctl list-unit-files | tr -s ' ' | cut -d \ -f1,2 | grep enabled | cut -d \ -f1
    – ericx
    Jun 16 at 11:45
3

You know the old joke where the dev goes "There is no bug, it works on my laptop!" so the colleague discovering the bug replies "So we'll ship your laptop"? When you try to make an exact copy of a production system, you are dangerously treading closer to that abyss.

Rather than reusing (in reality often partly unintended) artifacts of undocumented system state modification, place your intended state into the most expressive and consistently & hands-free deployable language you can (ansible is your friend), and store that in version control (git is your friend). Use snapshots of effective state (for that, rsync is probably good enough) for validating you have at least once perfected that method (comparing a automatically setup fresh system to your hand-crafted one), otherwise only for diagnostic & disaster recovery purposes.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .