Ansible 如何将set_fact和with_结合使用?

Ansible 如何将set_fact和with_结合使用?,ansible,ansible-2.x,ansible-facts,Ansible,Ansible 2.x,Ansible Facts,我试图转换来自远程机器上的属性文件的bash环境变量。我将密钥和值注册到两个寄存器变量,然后尝试使用with_循环它们,并设置_事实 以下是我如何寻找我的变量键/值 - name: Source Env Properties shell: . <source utility> && ( set -a posix ; set| sed 's,=.*,,' ) register: variable_keys - shell: . <source utili

我试图转换来自远程机器上的属性文件的bash环境变量。我将密钥和值注册到两个寄存器变量,然后尝试使用with_循环它们,并设置_事实

以下是我如何寻找我的变量键/值

- name: Source Env Properties
  shell: . <source utility> && ( set -a posix ; set| sed 's,=.*,,' )
  register: variable_keys

- shell: . <source utility> && ( set -a posix ; set| sed 's,^.*=,,' )
  register: variable_values
任务的输出似乎应该是有效的,但当试图使用这些变量时,它表示这些变量没有定义


有人能告诉我为什么这不起作用吗?

所以,正如我在评论中提到的,您的第一个问题是set\u事实块中的语法不正确。如果您有:

"{{item.0}}:{{item.1}}"
然后是单个字符串,而不是键:值对。您需要将其修改为

- name: set variables
  set_fact:
    "{{item.0}}": "{{item.1}}"
  with_together:
    - "{{ variable_keys.stdout_lines }}"
    - "{{ variable_values.stdout_lines }}"
但这只是问题的一半。sed表达式可能最终生成语法无效的输出,因为它们将包含bash函数定义。也就是说,如果在本地环境中运行第一个命令,那么输出将包括bash完成、git提示等shell函数中的所有cruft,如下所示:

scl () 
{ 
    local CMD
    if [ "$CMD" 
        eval "module $@";
    else
        /usr/bin/scl "$@";
    fi
}
- name: Source Env Properties
  shell: |
    set -a
    . ./myvars.sh
    jq -n env
  register: vars_raw

- set_fact:
    shellvars: "{{ vars_raw.stdout|from_json }}"

- debug:
    var: shellvars.FOO
这会让ansible崩溃:

failed: [localhost] (item=[u"'", u"'"]) => {"changed": false, "failed": true, "item": ["'", "'"], "msg": "The variable name ''' is not valid. Variables must start with a letter or underscore character, and contain only letters, numbers and underscores."}
你需要确保过滤掉这些内容。我用了这个:

- name: Source Env Properties
  shell: . ./myvars.sh && ( set -a posix; set| sed -n '/^[A-Z]/ s,=.*,,p' )
  register: variable_keys

- shell: . ./myvars.sh && ( set -a posix; set| sed -n '/^[A-Z]/ s,^.*=,,p' )
  register: variable_values

- name: set variables
  set_fact:
    "{{item.0}}": "{{item.1}}"
  with_together:
    - "{{ variable_keys.stdout_lines }}"
    - "{{ variable_values.stdout_lines }}"
如果我有,在myvars.sh中:

如果在我的剧本中我有,在上面:

- debug:
    var: FOO
我将看到以下输出:

ok: [localhost] => {
    "FOO": "bar"
}
顺便说一句,我认为所有这些与sed有关的事情都是脆弱的,并且可能会导致其他问题。我可能会这样做:

scl () 
{ 
    local CMD
    if [ "$CMD" 
        eval "module $@";
    else
        /usr/bin/scl "$@";
    fi
}
- name: Source Env Properties
  shell: |
    set -a
    . ./myvars.sh
    jq -n env
  register: vars_raw

- set_fact:
    shellvars: "{{ vars_raw.stdout|from_json }}"

- debug:
    var: shellvars.FOO
这使用jq将所有可用的环境变量导出为JSON,然后将结果分配给shellvars变量。其中的set-a确保将myvars.sh中设置的任何变量导出到环境中。如果手头没有jq,可以使用python:


我认为你的背景资料引用得太多了。尝试{{item.0}:{{item.1}}?@larsks获得相同的结果。没有错误,直到我尝试使用一个事实作为一个变量在剧本后面。非常感谢你的帮助。你是对的,在sed上胡闹是有问题的,但是你给我的sed提供的调整现在解决了我的问题。python解决方案也可以在我的大多数环境中工作,但不是所有环境都可以。
- name: Source Env Properties
  shell: |
    set -a
    . ./myvars.sh
    python -c 'import json; import os; print(json.dumps(dict(os.environ)))'
  register: vars_raw

- set_fact:
    shellvars: "{{ vars_raw.stdout|from_json }}"

- debug:
    var: shellvars.FOO