What is the best way to test (verify existence) for a systemd user service?

I have a role task which executes a script to install a systemd user (systemctl --user) service. I want to add a when condition to only execute the script when the service is not already installed.
I’m looking for the best solution to do it.

What I’ve tried:

  1. check with service
become: yes
become_user: user
ansible.builtin.service:
  name: my_service
check_mode: true
register: service_exist

[...]
when: not (service_exist is defined and service_exist | length > 0)

but it doesn’t work, service_exist is always a dict with a lot of information even when the service doesn’t exist and I don’t clearly see what property is different between an existing service and a non-existing one

  1. check with systemd_service and scope: user
become: yes
become_user: user
ansible.builtin.systemd_service:
  name: service
  state: started
  scope: user
check_mode: true
register: systemd_exist

[...]
when: systemd_exist

but this module fails when the service do not exist

fatal: [debian-12]: FAILED! => {"changed": false, "msg": "Could not find the requested service my_fake_service: host"}

Of course, i could simply test the existence of ~$user/.config/systemd/$service.service file but I would like to do it properly (and not need to retrieve the home directory before testing this)

Any idea?

You can set ignore_errors to true and handle it later with register and then a when condition of “is failed.”

You could also try using the block/rescue construct, it works like a try/except in Python. Something like:

block:
  - become: yes
    become_user: user
    ansible.builtin.systemd_service:
      name: service
      state: started
      scope: user
    check_mode: true
rescue:
  # You can use `ansible_failed_result` to parse the error message from the task, no need to `register` (unless you use it elsewhere)
  - name: run the script to install the service
    # whatever you use for that

See more about that in:

1 Like

You can also use https://docs.ansible.com/ansible/latest/collections/ansible/builtin/service_facts_module.html

2 Likes

@wayt @russoz I find those solutions a little bit ‘hacky’, the idea of try/except doesn’t looks fine for me in such situations where I only want to test a condition and get a true/false result.
It seems that Ansible doesn’t provide a proper solution, but then I prefer to use a less-than-ideal-one (see below)
(edit: not that hacky, because ignore_errors is configurable by task)

@bcoca I think those facts only works with systemd services on system scope, not on user one.

I think the best (in my case) solutions are:

  • verify the existence of the service systemd definition file, like ~/.config/systemd/$service.service
  • verify the real execution of the service with something a ps | grep with become_user. Not sure if I need to use ansible.builtin.shell or ansible.builtin.command but I’ll look and try

Hi @daks you’re absolutely right, and as you pointed out that service_facts does not handle “user” services, I am thinking of taking a look at the code and see if we can add it. Would be willing to do the honours and submit the contribution yourself? I 'd be more than happy to help.

1 Like

I’m not sure I have the skill and be able to find time to do it, but it could be interesting to try :slight_smile:

1 Like