嗨,我正在尝试找出如何使用Ansible设置环境变量。
就像这样一个简单的shell命令:
EXPORT LC_ALL=C
尝试作为Shell命令,但出现错误。尝试使用环境模块,但什么也没发生。我错过了什么?有多种方法可以做到这一点,从你的问题中无法确定你的需求。
1. 如果你需要每个任务都定义环境变量,则可以这样做:
- hosts: dev
tasks:
- name: Echo my_env_var
shell: "echo $MY_ENV_VARIABLE"
environment:
MY_ENV_VARIABLE: whatever_value
- name: Echo my_env_var again
shell: "echo $MY_ENV_VARIABLE"
请注意,MY_ENV_VARIABLE
仅在第一个任务中可用,environment
不会在您的系统上永久设置它。TASK: [Echo my_env_var] *******************************************************
changed: [192.168.111.222] => {"changed": true, "cmd": "echo $MY_ENV_VARIABLE", ... "stdout": "whatever_value"}
TASK: [Echo my_env_var again] *************************************************
changed: [192.168.111.222] => {"changed": true, "cmd": "echo $MY_ENV_VARIABLE", ... "stdout": ""}
希望不久之后,在游戏级别而非仅在任务级别上,也可以使用环境变量
。目前在 Ansible 的 GitHub 上有一个开放的 pull request 来实现这个功能:https://github.com/ansible/ansible/pull/8651
更新:此功能已于2015年1月2日合并。
2. 如果您想要永久性的环境变量 + 系统范围 / 仅适用于某个用户
您应该了解如何在您的 Linux 发行版 / shell 中进行操作,在那里有多个位置可以进行设置。例如,在 Ubuntu 中,您可以在以下文件中定义:
~/.profile
/etc/environment
/etc/profile.d
目录您可以在这里找到 Ubuntu 的相关文档:https://help.ubuntu.com/community/EnvironmentVariables
最后,要在 Ubuntu 中设置环境变量,您可以使用 Ansible 的 lineinfile
模块,并将所需的内容添加到某个文件中。请查阅您的操作系统文档以了解应该将其添加到哪个文件以使其永久生效。
我没有足够的声望来发表评论,因此我添加了一个新答案。
Gasek的答案相当正确。 只有一点:如果您正在更新.bash_profile
文件或/etc/profile
文件,则仅在进行新登录后才会反映这些更改。
如果您想设置环境变量,然后在同一剧本中的后续任务中使用它,请考虑将这些环境变量添加到.bashrc
文件中。
我猜原因是登录和非登录shell不同。
Ansible在执行不同任务时,从.bashrc
文件读取参数,而不是从.bash_profile
或/etc/profile
中读取。
例如,如果我在相应用户的.bash_profile
文件中更新了路径变量以包含自定义二进制文件,然后对该文件进行源操作。
下一个子任务将无法识别我的命令。但是如果您在.bashrc
文件中更新,则该命令将起作用。
- name: Adding the path in the bashrc files
lineinfile: dest=/root/.bashrc line='export PATH=$PATH:path-to-mysql/bin' insertafter='EOF' regexp='export PATH=\$PATH:path-to-mysql/bin' state=present
- - name: Source the bashrc file
shell: source /root/.bashrc
- name: Start the mysql client
shell: mysql -e "show databases";
这个方法是可行的,但如果我使用配置文件来做,mysql -e "show databases"
会报错。
- name: Adding the path in the Profile files
lineinfile: dest=/root/.bash_profile line='export PATH=$PATH:{{install_path}}/{{mysql_folder_name}}/bin' insertafter='EOF' regexp='export PATH=\$PATH:{{install_path}}/{{mysql_folder_name}}/bin' state=present
- name: Source the bash_profile file
shell: source /root/.bash_profile
- name: Start the mysql client
shell: mysql -e "show databases";
这个不起作用,如果我们将所有这些任务放在同一个playbook中。
以下是一个快速的本地任务,可以永久性地在 /etc/environment
上设置键/值(这是系统范围内的所有用户,需要成为 root 用户):
- name: populate /etc/environment
lineinfile:
path: "/etc/environment"
state: present
regexp: "^{{ item.key }}="
line: "{{ item.key }}={{ item.value}}"
with_items: "{{ os_environment }}"
become: yes
还有它的变量:
os_environment:
- key: DJANGO_SETTINGS_MODULE
value : websec.prod_settings
- key: DJANGO_SUPER_USER
value : admin
而且,如果你通过ssh退出并重新登录,env
会显示新的环境变量。
p.s. 以前是使用dest
,如下所示:
dest: "/etc/environment"
但是请注意评论。
———————
注意:下面的内容更多是观察/实验,而不是建议。 ———————
第一个任务相当于Michael的最受欢迎的答案。
第二个不起作用,但同样在bash中foo = 1 echo $ foo
也不起作用(我怀疑这是因为echo
是内置的)。
第三个确实起作用,就像在bash中一样,并且需要很少的努力。然而... 当我尝试将此应用于设置节点变量时,它失败了,直到我使用了Michael的答案。
tasks:
- name: Echo my_env_var
shell: "echo $MY_ENV_VARIABLE"
environment:
MY_ENV_VARIABLE: value1
- name: Echo my_env_var inline, doesnt work in bash either
shell: "MY_ENV_VARIABLE=value2 echo $MY_ENV_VARIABLE"
- name: set my_env_var inline then env
shell: "MY_ENV_VARIABLE=value3 env | egrep MY_ENV"
TASK [Echo my_env_var] *********************************************************
changed: [192.168.63.253] => changed=true
cmd: echo $MY_ENV_VARIABLE
stdout: value1
TASK [Echo my_env_var inline, doesnt work in bash either] **********************
changed: [192.168.63.253] => changed=true
cmd: MY_ENV_VARIABLE=value2 echo $MY_ENV_VARIABLE
stdout: ''
TASK [set my_env_var inline then env] ******************************************
changed: [192.168.63.253] => changed=true
cmd: MY_ENV_VARIABLE=value3 env | egrep MY_ENV
stdout: MY_ENV_VARIABLE=value3
$ printenv
- Trevor Nathan这是最佳选择。正如 Michal Gasek(第一个回答者)所说,自从合并拉取请求以来(https://github.com/ansible/ansible/pull/8651),我们可以轻松地在 play 层级设置 永久环境变量。
- hosts: all
roles:
- php
- nginx
environment:
MY_ENV_VARIABLE: whatever_value
如果您需要持久设置环境变量,可以在Ansible Galaxy上使用现有的角色之一。我建议使用weareinteractive.environment。
使用ansible-galaxy:
$ ansible-galaxy install weareinteractive.environment
使用 requirements.yml:
- src: franklinkim.environment
然后在你的playbook中:
- hosts: all
sudo: yes
roles:
- role: franklinkim.environment
environment_config:
NODE_ENV: staging
DATABASE_NAME: staging
krew
插件管理器和一些其插件,使用ansible
来为Fish
shell进行操作。为了安装这些插件,我想使用由之前在/.config/fish/config.fish
中设置的$PATH值。
使用带有executable
参数的shell
模块会抛出以下错误:
stderr: |-
error: unknown command "krew" for "kubectl"
error: unknown command "krew" for "kubectl"
error: unknown command "krew" for "kubectl"
add a line declaring the path to the krew bin in /.config/fish/config.fish
- name: Add krew to $PATH
lineinfile:
path: '{{ home }}/.config/fish/config.fish'
search_string: krew
line: set --append --export --global PATH $HOME/.krew/bin
Then, use the shell
module to source Fish config file and run kubectl
commands to install my plugins:
- name: Install `kubectx` (context) and `kudens` (namespace)
shell: |
source {{ home }}/.config/fish/config.fish
kubectl krew install ctx
kubectl krew install ns
kubectl krew install oidc-login
args:
executable: /usr/bin/fish
看起来有点像黑客式的解决方案,我更希望有更多类似 Ansible 的解决方案。
你也可以使用自定义的插件来设置环境变量
主机设置
ansible_become=yes
ansible_become_method=foo
become_plugins/foo.py
from ansible.plugins.become import BecomeBase
class BecomeModule(BecomeBase):
def build_become_command(self, cmd, shell):
cmd = 'PYTHONPATH="/foo/bar:$PYTHONPATH" ' + cmd
return cmd