- 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
- ...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
- see
man sh
... When invoked as an interactive shell with the name
sh
,bash
looks for the variableENV
, 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 variableBASH_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.
echo "localhost" > inventory
ansible localhost -a 'echo $PATH'
- you will see the full path of current shell
ansible -c ssh -i inventory localhost -a 'echo $PATH'
- you will see the standard
PATH=/usr/bin:/bin:/usr/sbin:/sbin
ansible -b --become-user=test -c ssh -i inventory localhost -a 'echo $PATH'
- no change, still only the default path
- 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
.profile
or.bash_profile
or.bash_rc
are not read by default, neither are system wide config filesENV
is not used when executed with/bin/sh
, although it says so inman bash
BASH_ENV
is loaded when executable is/bin/bash
- ansible
command
module always uses/bin/sh
so you need to use theshell
module - --> set
BASH_ENV
to either global/etc/profile
or user~/.profile
as desired
- 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 theshell
module.- To make the
pip
module work again, you have to usePATH
environment for the role
- To make the
Thank you for your effort. My solution on this - just hardcode the environment globally in a playbook. (
BASH_ENV
didn't work for me for some reason)Pros - it works. Cons - you must exactly know which PATH you're trying to achieve.
For basic stuff like rbenv, homebrew (w/ Apple Silicon
/opt/
supported paths) I have setup below