如何使用 set_fact 和 with_together?

How can I use set_fact and with_together?

我正在尝试转换 bash 源自远程计算机上的属性文件的环境变量。我正在将键和值注册到两个寄存器变量,然后尝试使用 with_togetherset_fact

循环遍历它们

这是我获取变量的方式key/values

- 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_fact使用两个注册值。

- name: set variables
  set_fact:
     "{{item.0}}:{{item.1}}"
  with_together:
    - "{{ variable_keys.stdout_lines }}"
    - "{{ variable_values.stdout_lines }}"

任务的输出看起来应该可以工作,但是当尝试使用这些变量时,它说它们没有定义。

谁能告诉我为什么这不起作用?

因此,正如我在评论中提到的,您的第一个问题是 set_fact 块中的语法不正确。如果你有这个:

"{{item.0}}:{{item.1}}"

那么你只有一个字符串,而不是 key: value 对。您需要将其修改为

- name: set variables
  set_fact:
    "{{item.0}}": "{{item.1}}"
  with_together:
    - "{{ variable_keys.stdout_lines }}"
    - "{{ variable_values.stdout_lines }}"

但这只是问题的一半。您的 sed 表达式最终可能会产生语法上无效的输出,因为它们将包含 bash 函数定义。也就是说,如果我 运行 我本地环境中的第一个命令,输出包括来自 shell 函数的所有内容,用于 bash 完成、git 提示等,像这样:

scl () 
{ 
    local CMD
    if [ "$CMD" 
        eval "module $@";
    else
        /usr/bin/scl "$@";
    fi
}

这将破坏 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:

FOO=bar

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

- debug:
    var: FOO

我将看到输出:

ok: [localhost] => {
    "FOO": "bar"
}

顺便说一句,我认为 sed 的所有这些乱七八糟的事情很脆弱,可能会在未来引起其他问题。我可能会这样做:

- 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:

- 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