# How to set an environment variable depending of a shell command

**URL:** <https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585>\
**Category:** Get Help\
**Created:** [October 29, 2024, 10:13pm UTC](https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585 "2024-10-29T22:13:53Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![daks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/daks/32/5277_2.png) [@daks](https://forum.ansible.com/u/daks)\
**Post date:** [October 29, 2024, 10:13pm UTC](https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585/1 "2024-10-29T22:13:53Z")

</div>

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:

```auto
- 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.

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [October 30, 2024, 12:33am UTC](https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585/2 "2024-10-30T00:33:20Z")

</div>

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.

```yaml
---
# 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 }}'

```

The output from the last task looks like this:

```txt
TASK [Do stuff with id_u] **************************************************************************************
changed: [localhost] => (item=gdm) => changed=true 
  ansible_loop_var: item
  cmd: |-
    printf "%s:: idu=%s, MY_VAR=%s\n" "gdm" "42" "$MY_VAR"
  delta: '0:00:00.002974'
  end: '2024-10-29 20:31:34.941036'
  item: gdm
  msg: ''
  rc: 0
  start: '2024-10-29 20:31:34.938062'
  stderr: ''
  stderr_lines: <omitted>
  stdout: 'gdm:: idu=42, MY_VAR=/var/run/user/42'
  stdout_lines: <omitted>
changed: [localhost] => (item=sshd) => changed=true 
  ansible_loop_var: item
  cmd: |-
    printf "%s:: idu=%s, MY_VAR=%s\n" "sshd" "74" "$MY_VAR"
  delta: '0:00:00.002834'
  end: '2024-10-29 20:31:35.119171'
  item: sshd
  msg: ''
  rc: 0
  start: '2024-10-29 20:31:35.116337'
  stderr: ''
  stderr_lines: <omitted>
  stdout: 'sshd:: idu=74, MY_VAR=/var/run/user/74'
  stdout_lines: <omitted>
changed: [localhost] => (item=no_id_bbb) => changed=true 
  ansible_loop_var: item
  cmd: |-
    printf "%s:: idu=%s, MY_VAR=%s\n" "no_id_bbb" "missing" "$MY_VAR"
  delta: '0:00:00.002766'
  end: '2024-10-29 20:31:35.295585'
  item: no_id_bbb
  msg: ''
  rc: 0
  start: '2024-10-29 20:31:35.292819'
  stderr: ''
  stderr_lines: <omitted>
  stdout: 'no_id_bbb:: idu=missing, MY_VAR=/var/run/user/missing'
  stdout_lines: <omitted>

```

* * *

To do it in one task…

```yaml
    - name: Do it in one task
      ansible.builtin.shell: |
        id="{{ item }}"
        idu="$( id -u "{{ item }}" 2>/dev/null )"
        if [-n "$idu"] ; then
          export MY_VAR="/var/run/user/${idu}"
          echo $MY_VAR # my_shell_command
        fi
      loop:
        - gdm
        - sshd
        - no_id_ccc

```

which outputs this:

```txt
TASK [Do it in one task] ***************************************************************************************
changed: [localhost] => (item=gdm) => changed=true 
  ansible_loop_var: item
  cmd: |-
    id="gdm"
    idu="$( id -u "gdm" 2>/dev/null )"
    if [-n "$idu"] ; then
      export MY_VAR="/var/run/user/${idu}"
      echo $MY_VAR # my_shell_command
    fi
  delta: '0:00:00.004189'
  end: '2024-10-29 20:26:11.061616'
  item: gdm
  msg: ''
  rc: 0
  start: '2024-10-29 20:26:11.057427'
  stderr: ''
  stderr_lines: <omitted>
  stdout: /var/run/user/42
  stdout_lines: <omitted>
changed: [localhost] => (item=sshd) => changed=true 
  ansible_loop_var: item
  cmd: |-
    id="sshd"
    idu="$( id -u "sshd" 2>/dev/null )"
    if [-n "$idu"] ; then
      export MY_VAR="/var/run/user/${idu}"
      echo $MY_VAR # my_shell_command
    fi
  delta: '0:00:00.004255'
  end: '2024-10-29 20:26:11.246869'
  item: sshd
  msg: ''
  rc: 0
  start: '2024-10-29 20:26:11.242614'
  stderr: ''
  stderr_lines: <omitted>
  stdout: /var/run/user/74
  stdout_lines: <omitted>
changed: [localhost] => (item=no_id_ccc) => changed=true 
  ansible_loop_var: item
  cmd: |-
    id="no_id_ccc"
    idu="$( id -u "no_id_ccc" 2>/dev/null )"
    if [-n "$idu"] ; then
      export MY_VAR="/var/run/user/${idu}"
      echo $MY_VAR # my_shell_command
    fi
  delta: '0:00:00.005363'
  end: '2024-10-29 20:26:11.421682'
  item: no_id_ccc
  msg: ''
  rc: 0
  start: '2024-10-29 20:26:11.416319'
  stderr: ''
  stderr_lines: <omitted>
  stdout: ''
  stdout_lines: <omitted>

```

---

<div class="post-metadata">

**Author:** ![daks](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/daks/32/5277_2.png) [@daks](https://forum.ansible.com/u/daks)\
**Post date:** [October 30, 2024, 3:35pm UTC](https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585/3 "2024-10-30T15:35:25Z")

</div>

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 🙂

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/ansible/original/1X/1882d9a01da5d8996a862359b0913cc568a39b84.svg) [@system](https://forum.ansible.com/u/system)\
**Post date:** [November 29, 2024, 3:36pm UTC](https://forum.ansible.com/t/how-to-set-an-environment-variable-depending-of-a-shell-command/10585/4 "2024-11-29T15:36:16Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
