Ansible become_user not picking up path correctly

Here's the code showing what I believe is a problem:

# Debugging path problems with sudo
---
- hosts: webservers
  remote_user: root
  tasks:
  - name: echo path
    command: echo $PATH
    register: output
    changed_when: False

  - name: display root path output
    debug: "msg={{ output.stdout }}"

  # Now try as apache
  - name: echo path
    command: echo $PATH
    become: true
    become_user: apache
    become_method: sudo
    register: output
    changed_when: False

  - name: display wrong output
    debug: "msg={{ output.stdout }}"

  # This is the fix
  - name: echo path
    command: echo $PATH
    environment:
      PATH: "{{ ansible_env.PATH }}"
    become: true
    become_user: apache
    become_method: sudo
    register: output
    changed_when: False

  - name: display fixed output
    debug: "msg={{ output.stdout }}"

Here's the output, you can see that the path is not complete without adding "the fix".

TASK [echo path] ***************************************************************
ok: [webapp]

TASK [display root path output] ************************************************
ok: [webapp] => {
    "changed": false, 
    "msg": "/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
}

TASK [echo path] ***************************************************************
ok: [webapp]

TASK [display wrong output] ****************************************************
ok: [webapp] => {
    "changed": false, 
    "msg": "/sbin:/bin:/usr/sbin:/usr/bin"
}

TASK [echo path] ***************************************************************
ok: [webapp]

TASK [display fixed output] ****************************************************
ok: [webapp] => {
    "changed": false, 
    "msg": "/usr/lib64/qt-3.3/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
}

Why is this fix necessary, is this a bug?

This is on CentOS 6.7 and using Ansible 2.0


Solution 1:

This is normal and expected behavior.

Remember that sudo sanitizes the environment when switching users, which is why you end up with a minimal default PATH.

The remainder of the items in the PATH come from shell startup scripts, which are not being run when you (or rather Ansible) call sudo <command>, because it is not asking for an interactive or login shell.

If you have to run a command which isn't in a default location, supply its path explicitly.