I’m trying to run a command on a set of users. This command needs an environment variable which is different for each user and its value comes from a ‘shell command’.
An example:
- name: Run a command per user
become: yes
become_user: "{{ item }}"
ansible.builtin.command: my-shell-command
environment:
MY_VAR: /var/run/user/$(id -u)
loop: ['user1', 'user2']
The MY_VAR variable depends of the result of id -u.
Is it possible to set it directly and how?
Or do I need to use an intermediate step to run the id -u command for each user and register it?
In which case how to simply retrieve the specific stdout value for each user? I got a very complicated dict as a result and I’m not sure how to simply use it.
You could do it in one task if you’re willing to use ansible.builtin.shell instead of ansible.builtin.command. I’ll show that later.
First, I want to show you how you can do it with an intermediate step. This should give you enough to get started. Note that my system has users sshd and gdm, but not no_id_aaa or no_id_bbb. I’m including both so you can experiment with how to handle missing ids, both when you first look them up and when you later try to use a missing registered result.
---
# daks_01.yml
- name: Id -u for multiple users
hosts: localhost
gather_facts: false
tasks:
- name: Get id -u for users
ansible.builtin.shell: |
id -u {{ item }} || echo "no_such_id"
register: id_u_reg
loop:
- sshd
- gdm
- no_id_aaa
- name: Dump registered data
ansible.builtin.debug:
msg: '{{ id_u_reg }}'
- name: Do stuff with id_u
ansible.builtin.shell: |
printf "%s:: idu=%s, MY_VAR=%s\n" "{{ item }}" "{{ idu }}" "$MY_VAR"
loop:
- gdm
- sshd
- no_id_bbb
environment:
MY_VAR: '/var/run/user/{{ idu }}'
vars:
idu: '{{ [id_u_reg.results
| selectattr("item", "eq", item)
| map(attribute="stdout"), "missing"
] | flatten
| first }}'
Thank you very much for this detailed answer with the two possibilities.
I’m still not sure the one I’ll use, the short more cryptic (and a little bit less secure, because it uses shell instead of command) one or the longer clearer one.
I’ll first try both to better understand how they works