Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save seansaleh/307c1ef66cd694b92e7a181f6c1b0689 to your computer and use it in GitHub Desktop.
Save seansaleh/307c1ef66cd694b92e7a181f6c1b0689 to your computer and use it in GitHub Desktop.
macOS / OSX ansible path test

INFO

  • remote SSH shell on macOS does not use /etc/paths
  • this is not an issue of ansible, it is the way macOS processes config files on remote shells:
  • see ssh localhost echo \$PATH

ANSIBLE executes remote shell /bin/sh

  • ...if not specified otherwise and macOS does not read any startup files
  • example: [...]localhost '/bin/sh -c '"'"'sudo -H -S -n -u test /bin/sh -c '"'"'"'"'"[...]
  • even /bin/bash does not read any startup files by default

Documentation

  • see man sh

... When invoked as an interactive shell with the name sh, bash looks for the variable ENV, expands its value if it is defined, and uses the expanded value as the name of a file to read and execute....

  • and

When bash is started non-interactively, to run a shell script, for example, it looks for the variable BASH_ENV in the environment, expands its value if it appears there, and uses the expanded value as the name of a file to read and execute.

Tests

required to SSH to localhost

echo "localhost" > inventory

execute local as current user (no ssh, just exec)

ansible localhost -a 'echo $PATH'

  • you will see the full path of current shell

local through ssh as root

ansible -c ssh -i inventory localhost -a 'echo $PATH'

  • you will see the standard PATH=/usr/bin:/bin:/usr/sbin:/sbin

as user

ansible -b --become-user=test -c ssh -i inventory localhost -a 'echo $PATH'

  • no change, still only the default path

SOLUTION

  • add BASH_ENV=~/.profile into the environment of the playbook/role,
  • unfortunately that does not work with ad-hoc commands, so we need a playbook
  • simple playbook test_env_playbook.yml
---
- name: Test ENV
  hosts: localhost
  environment:
    BASH_ENV: "~/.profile"
    # also possible, but not using hosts config PATH: "{{ ansible_env.PATH }}:/usr/local/bin"
  tasks:
    - name: Echo PATH
      shell: echo $PATH
      args:
        executable: /bin/bash
      become: yes
      become_user: "test"
  • run it (very verbose) ansible -i inventory test_env_playbook.yml -vvv

RESULTS

  • .profile or .bash_profile or .bash_rc are not read by default, neither are system wide config files
  • ENV is not used when executed with /bin/sh, although it says so in man bash
  • BASH_ENV is loaded when executable is /bin/bash
  • ansible command module always uses /bin/sh so you need to use the shell module
  • --> set BASH_ENV to either global /etc/profile or user ~/.profile as desired

My setup

  • I create a ~/.profile on the root and user accounts
  • I load defaults from my user profile: echo 'source /etc/profile' >> ~/.profile
  • Benefit: I can use for example python/pip installed in my user Library directory
  • Downside: the ansible pip module does not work if its installed in /usr/local/bin folder, so you need to use the shell module.
    • To make the pip module work again, you have to use PATH environment for the role
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment