【问题标题】:Ansible - environment variables from .env fileAnsible - 来自 .env 文件的环境变量
【发布时间】:2020-02-13 13:38:49
【问题描述】:

我正在尝试设置一个剧本,它将运行命令来检查目标机器中安装的服务的状态。该命令仅在 .env file 执行时才有效。执行.env file 的命令是.<space>./.env_file_name,该文件包含环境变量列表,如导出JAVA_HOME=/optware/java/jdk/1.2.

我尝试在使用以下 playbook 运行命令之前执行环境文件,但它不起作用。

- hosts: name
  tasks: 
    - name: `execute env file`
      command: . ./.env_file_name
      register: result

是否有任何剧本可以运行可执行环境文件来设置目标机器上存在的环境,然后运行我们的命令??

【问题讨论】:

  • 通常 .env 或任何其他文件在 shell 中使用 source 关键字获取。试试看。 command: source <path>
  • 您希望在其他任务中使用环境变量吗?因为这是不可能的。如果你想在同一个任务中使用它们,那么你应该使用shell module。否则,要在任务执行中使用环境变量,需要使用environment keyword
  • @Zigarn 我需要在其他任务中使用环境变量。你有任何示例剧本来运行 .env 文件并在其他任务中使用 env 变量
  • 注意,.source 命令实际上是相同的:stackoverflow.com/a/20097303/320399

标签: ansible environment-variables


【解决方案1】:

首先. ./.env_file_name语法是shell语法,不能和command module一起使用,需要使用shell module

其次,每个任务都会重置 shell 环境上下文,因为每个任务都是一个 ssh 命令往返(因此是一个新的 shell 会话),并且在一个任务中加载环境变量不会使它们可用于下一个任务。

根据您的上下文,您有一些选择:

1。清点环境变量

最好的选择是通过group_vars/host_vars 将库存端的环境放在一个变量中,每个组/主机具有不同的值,然后将其用于environment keyword

# host_vars/my_host.yml
---
env_vars:
  VAR1: key1
  VAR2: key2
- hosts: my_host
  tasks: 
    - name: Display environment variables
      command: env
      environment: "{{ env_vars }}"

优点:

  • 完整的 ansible 解决方案
  • 适用于每个模块的环境

缺点:

  • 需要知道ansible端的环境变量

2。为每个任务加载环境变量

如果你的任务都是shell/command(我不建议这样做,因为最好尽可能使用适当的ansible module),你可以简单地每次使用shell模块加载env文件

- hosts: my_host
  tasks: 
    - name: Display environment variables
      shell: |
        . ./.env_file_name && env

    - name: Do another action
      shell: |
        . ./.env_file_name && do_something_else

优点:

  • 无需知道ansible端的环境变量

缺点:

  • 仅限于带有shell 模块的任务

3。将 env_file 中的环境变量加载到 ansible fact 中

此选项是一劳永逸地解析 env 文件并将其加载到 ansible fact 中以与 environment 关键字一起使用。

- hosts: my_host
  tasks: 
    - name: Get env file content
      slurp:
        src: ./.env_file_name
      register: env_file_content

    - name: Parse environment
      set_fact:
        env_vars: "{{ ('{' + (env_file_content.content | b64decode).split('\n') | select | map('regex_replace', '([^=]*)=(.*)', '\"\\1\": \"\\2\"') | join(',') + '}') | from_json }}"

    - name: Display environment variables
      command: env
      environment: "{{ env_vars }}"

或者,如果需要执行env文件而不是直接解析:

- hosts: my_host
  tasks: 
    - name: Get env file content
      shell: . ./.env_file_name && env
      register: env_file_result

    - name: Parse environment
      set_fact:
        env_vars: "{{ ('{' + env_file_result.stdout_lines | map('regex_replace', '([^=]*)=(.*)', '\"\\1\": \"\\2\"') | join(',') + '}') | from_json }}"

    - name: Display environment variables
      command: env
      environment: "{{ env_vars }}"

优点:

  • 适用于每个模块的环境
  • 无需知道ansible端的环境变量

缺点:

  • 可能因文件格式错误而失败

【讨论】:

  • 谢谢!虽然我认为最大的问题是正则表达式,因为它不支持值的引号,也不支持 cmets (#)。
  • 对!可以通过在 | map('regex_replace' 之前添加 | map('regex_replace', '#.*', '') | map('trim') | reject() 来删除 cmets 并将正则表达式更改为 '([^=]*)=['"]?(.*)['"]?' 来处理引用值的简单情况。
  • 所以我按照您的指示使用了:{{ ('{' + (env_file_content.content | b64decode).split('\n') | select | map('regex_replace', '#.*', '') | map('trim') | reject() | map('regex_replace', '([^=]*)=['\"]?(.*)['\"]?', '\"\\1\": \"\\2\"') | join(',') + '}') | from_json }},但不幸的是这不起作用。虽然我觉得这可能更倾向于一个单独的问题,但你知道我错过了什么吗?
  • 我认为我错了(没有测试...):使用select 而不是reject
猜你喜欢
  • 1970-01-01
  • 2018-12-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-27
  • 2019-12-22
  • 1970-01-01
相关资源
最近更新 更多