3

My situation

I installed a few new unit files under $HOME/.local/share/systemd/user/

ls -1 $HOME/.local/share/systemd/user/
some.service
some.timer
some_other.service

I ran the following command to have them loaded properly: systemctl --user daemon-reload

They show up in auto completion of systemctl --user enable <tab> <tab>. What I'm looking for is a way to later write a script with gum to show me a list of those units which are currently not enabled to enable them.

My question

Is there a better way than ls -1 $HOME/.local/share/systemd/user/ to get the list I'm looking for?

systemctl knows about the units through auto completion, but I don't want to that deep for a seemingly rather simple question. I looked at systemctl list all possible (including disabled) services and some parts of the Systemd documentation, but I wasn't able to find what I was looking for yet. It doesn't have to be perfect, the auto complete list also has some other entries which I could filter out. That won't be a problem for me.

2 Answers2

6

In general, systemctl --user list-unit-files shows the list of all user services.

So you can run the following command in order to get the list of user services that are disabled:

systemctl --user --full --no-legend --no-pager list-unit-files --state=disabled

By the way, you can look at the bash completion file of systemctl to see how it gets the list of disabled services, which is very similar:


__systemctl() {
    local mode=$1; shift 1
    systemctl $mode --full --legend=no --no-pager --plain "$@" 2>/dev/null
}

[...]

__get_disabled_units() { __systemctl $1 list-unit-files "$2*"
| while read -r a b c ; do [[ $b == "disabled" ]] && echo " $a"; done; }

You can also find this file on your local machine. In my case it's located at /usr/share/bash-completion/completions/systemctl, but I'm not sure if it's the standard path for all disros.

aviro
  • 5,532
  • Thank you! I was wondering what kind of magic would be at play. Now I see that echo " $a" outputs the first column (= unit file name). Ok, now I don't have to feel ashamed for using awk {print $1} to get what I want. The path to bash completers should be pretty much standardized in distributions which integrate Systemd. For Ubuntu it is https://packages.ubuntu.com/noble/amd64/systemd/filelist the same, for other distributions the quickest way I know of would be https://pkgs.org/search/?q=systemd&on=files and looking at the file list. :-) – LiveWireBT Jan 23 '24 at 00:39
5

aviro's answer motivated me to spend a bit more time on this. This is what I came up with now:

SYSTEMD_COLORS=no systemctl list-unit-files \
    --full \
    --no-legend \
    --no-pager \
    --state=disabled \
    --type=service,timer \
    --user \
| sort \
| awk '!/^(obex|rygel|wireplumber)(@)?\.(service|timer)/ {print $1}'
  • You don't need SYSTEMD_COLORS=no, systemctl itself should detect that its output is sent to a pipe, but I leave it here for readers who will be further experimenting with the code.

  • I included --type=service,timer because I had at least one .socket unit in my list.

  • obex|rygel|wireplumber is a list of units I don't want to have in the selection. If you want to use an allow list instead of a deny list, you need to remove ! at the beginning.

As I wrote in my question, I further process this with gum, so awk is followed by | gum choose in my script. It makes sense when you look at the project's site.