如何使用Ansible设置Linux环境变量

154

嗨,我正在尝试找出如何使用Ansible设置环境变量。

就像这样一个简单的shell命令:

EXPORT LC_ALL=C
尝试作为Shell命令,但出现错误。尝试使用环境模块,但什么也没发生。我错过了什么?
7个回答

227

有多种方法可以做到这一点,从你的问题中无法确定你的需求。

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 模块,并将所需的内容添加到某个文件中。请查阅您的操作系统文档以了解应该将其添加到哪个文件以使其永久生效。


47

我没有足够的声望来发表评论,因此我添加了一个新答案。
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中。


你能在同一个playbook中运行所有任务吗?还是需要使用不同的plays?或者必须放在不同的playbooks中?我已经尝试过了... - Cir02

46

以下是一个快速的本地任务,可以永久性地在 /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

对于第一种解决方案: 要确认环境变量已设置,请检查您的 /etc/environment 文件。 $ printenv - Trevor Nathan

14

这是最佳选择。正如 Michal Gasek(第一个回答者)所说,自从合并拉取请求以来(https://github.com/ansible/ansible/pull/8651),我们可以轻松地在 play 层级设置 永久环境变量

- hosts: all
  roles:
     - php
     - nginx
  environment:
    MY_ENV_VARIABLE: whatever_value

12

如果您需要持久设置环境变量,可以在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

1
我正在安装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"

解决方案
  1. 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
    
  2. 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 的解决方案。


0

你也可以使用自定义的插件来设置环境变量

主机设置

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接