Ansible 中的全局修改 $PATH 无法在常规 Linux shell 中按预期工作
Posted
技术标签:
【中文标题】Ansible 中的全局修改 $PATH 无法在常规 Linux shell 中按预期工作【英文标题】:Global modified $PATH in Ansible not working as expected from regular Linux shell 【发布时间】:2019-08-07 12:42:31 【问题描述】:我想下载一些像Helm 这样的二进制文件,并使用$PATH
使它们在全球范围内可用。为了避免使用 root 权限下载或者必须执行步骤(使用标准用户下载并移动到 $PATH
中的某个 bin 文件夹,例如 /usr/local/bin
),我的想法是创建 $HOME/bin
并将其添加到 $PATH
。
This blog article 用于向/etc/environment
添加自定义路径。然后我将其重新加载为described here。这是我的 POC 手册,我尝试在其中添加 exa:
- name: Test
hosts: all
vars:
- bin: /home/vagrant/bin
tasks:
- name: Test task
file:
path: "bin"
state: directory
- name: Add bin to path
become: yes
lineinfile: >
dest=/etc/environment
state=present
backrefs=yes
regexp='PATH=(["]*)((?!.*?bin).*?)(["]*)$'
line="PATH=\1\2:bin\3"
- name: Check path1
shell: echo $PATH
- name: Download exa
unarchive:
src: https://github.com/ogham/exa/releases/download/v0.8.0/exa-linux-x86_64-0.8.0.zip
dest: "bin"
remote_src: yes
- name: reload env file
shell: for env in $( cat /etc/environment ); do export $(echo $env | sed -e 's/"//g'); done
- name: Check path after reload env file
shell: echo $PATH
- name: Test exa from PATH
shell: exa-linux-x86_64 --version
在最后一个 tash Test exa from PATH
它抛出错误:
"stderr": "/bin/sh: 1: exa-linux-x86_64: not found"
echo $PATH
命令都保留在
"stdout": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
但修改后的/etc/environment
有效。当我在没有 ansible 的情况下在机器上使用 ssh 时,$PATH
很好,exa-linux-x86_64 --version
也可以:
~$ echo $PATH
/home/vagrant/bin:/home/vagrant/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/vagrant/bin:/snap/bin
环境
运行 Vagrant 的 Ubuntu 18.04 主机系统和 Ubuntu 16.04 机器。 Ansible 由 Vagrant 在 Ubuntu 16.04 上执行。
可能的解决方法
使用单独的环境变量
这样设置环境变量时
- name: Test exa from PATH
shell: exa-linux-x86_64 --version
environment:
PATH: " ansible_env.PATH :bin"
它有效。但我必须至少在游戏层面应用这些线。我想像 /etc/environment
在常规 shell 中那样全局设置它。 This questions 似乎有相同的目标,但在 Solaris 上。 answear 似乎只从主机设置$PATH
,这对我没有用,因为自定义 bin 目录不存在。
只使用绝对路径
- name: Test exa from PATH
shell: "bin/exa-linux-x86_64 --version"
这会减少开销,但您必须记住始终使用路径变量作为命令的前缀。似乎也容易出错
了解问题
我想要一个真正的解决方案,并了解导致问题的原因。我不清楚为什么 $PATH
修改在 Ansible 上如此困难,在底层 linux 系统中可以很容易地完成。 This question 说我们在 ansible 中没有交互式会话。似乎没有可用的$PATH
。根据the documentation,我们可以通过将-l
传递给bash 来归档它。所以我发现以下工作:
- name: Test exa from PATH
shell: bash -l -c "exa-linux-x86_64 --version"
但以下导致错误:
- name: Test exa from PATH
shell: exa-linux-x86_64 --version
args:
executable: /bin/bash -l
这里 Ansible 通过错误引用 args 来中断命令:
"'/bin/bash -l' -c 'exa-linux-x86_64 --version'"
This ticket 建议 Ansible 团队修复此问题,以便我们获得带有 $PATH
的登录 shell。自 2014 年以来,根本没有提供真正的解决方案。
问题
-
访问修改后的
$PATH
的不同shell 类型的目的是什么?
为什么 Ansible 会使事情复杂化?提供一个解决这个问题的登录shell不是更容易吗?他们这样做有什么原因吗?
我们如何处理由此产生的问题?什么是最佳实践?
【问题讨论】:
@jww:这是一个编程和开发问题。我认为这是“软件开发独有的实用、可回答的问题”。 Ansible 是否是开发的一部分是有争议的。管理员和开发人员越来越融合。尤其是在这个问题被要求构建一个本身应该作为开发平台的 Kubernetes 集群的情况下。但我认为这不能证明我得到的反对票是合理的,因为这个问题本身就是一个有效的问题——如果他在 SO 或被转移到 DevOps 等其他平台(可以转移),则独立。 @VladimirBotka 我会更进一步:编写 Ansible 配置是软件开发,只是不使用通用编程语言。 【参考方案1】:回答你的问题
1) 访问修改后的 $PATH 的不同 shell 类型的目的是什么?
在 Ansible 支持的所有操作系统中统一它是不值得的。这也解释了“我不清楚为什么在 Ansible 上修改 $PATH 如此困难,而在底层 linux 系统中可以很容易地完成。”
2) 为什么 Ansible 会使事情复杂化?提供一个解决这个问题的登录shell不是更容易吗?他们这样做有什么理由吗?
相反,不关心它更容易。保持简单愚蠢是原因。
3) 我们如何处理由此产生的问题?最佳做法是什么?
几十年来的最佳实践是Tools, no policy
【讨论】:
以上是关于Ansible 中的全局修改 $PATH 无法在常规 Linux shell 中按预期工作的主要内容,如果未能解决你的问题,请参考以下文章