Ansible为什么不将值从`stdout`分配给变量,而只分配给注册的变量名?

huangapple go评论62阅读模式
英文:

Why is Ansible not assigning the value from `stdout` and instead only the registered variable name?

问题

这似乎是一件简单的事情,我以前做过很多次,但最近开始注意到一些问题。也许我只是忽略了一些愚蠢的东西。

我有一些非常简单的任务:

- name: 测试注册
  ansible.builtin.shell: echo something
  register: test_value

- name: 输出测试值
  ansible.builtin.debug:
    msg: "{{ test_value }}"

这些任务的结果是:

任务 [foo/bar : 测试注册] *******************************************************************************
已更改:[test_host] => {"changed": true, "cmd": "echo something", "delta": "0:00:00.002040", "end": "2023-05-24 05:49:06.107897", "msg": "", "rc": 0, "start": "2023-05-24 05:49:06.105857", "stderr": "", "stderr_lines": [], "stdout": "something", "stdout_lines": ["something"]}

任务 [foo/bar : 输出测试值] ***************************************************************************
已完成:[test_host] => {
"msg": "test_value"
}

Ansible 版本:

ansible [core 2.13.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.13 (main, Nov  9 2022, 13:16:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)]
  jinja version = 3.1.2
  libyaml = True

为什么我只得到了注册变量的名称,而没有实际的 stdout 内容呢?这对我来说似乎也是不一致的。

英文:

This seems like a simple thing and I have done it many times before, but I started to notice some issues lately. Maybe I am just missing something dumb.

I have some pretty simply plays:

- name: Test register
  ansible.builtin.shell: echo something
  register: test_value

- name: Output test value
  ansible.builtin.debug:
    msg: "{{ test_value }}"

The results of these plays are:

TASK [foo/bar : Test register] *******************************************************************************
changed: [test_host] => {"changed": true, "cmd": "echo something", "delta": "0:00:00.002040", "end": "2023-05-24 05:49:06.107897", "msg": "", "rc": 0, "start": "2023-05-24 05:49:06.105857", "stderr": "", "stderr_lines": [], "stdout": "something", "stdout_lines": ["something"]}

TASK [foo/bar : Output test value] ***************************************************************************
ok: [test_host] => {
"msg": "test_value"
}

Ansible version:

ansible [core 2.13.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.13 (main, Nov  9 2022, 13:16:24) [GCC 8.5.0 20210514 (Red Hat 8.5.0-15)]
  jinja version = 3.1.2
  libyaml = True

Why is it that I am only getting the registered variable name and not actually the stdout contents? This seems to also be inconsistent for me as well.

答案1

得分: 1

根据返回值

> Ansible模块通常会返回一个可以注册到变量中的数据结构...

以及注册变量

> 注册变量可以是简单变量、列表变量、字典变量或复杂嵌套数据结构。每个模块的文档中都包含了一个RETURN部分,描述了该模块的返回值。

在你的情况下,shell模块 – 在目标上执行shell命令 - 返回值

> 我只获取到了注册的变量名,而没有实际的stdout内容?

如你从输出中看到的:

"stdout": "something", "stdout_lines": ["something"]

你应该通过以下方式获取:

- name: 输出测试值
  ansible.builtin.debug:
    var: test_value

- name: 输出测试值
  ansible.builtin.debug:
    var: test_value.stdout

对我来说,无法产生一个行为与最小示例剧本相同:

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - shell:
      cmd: "echo something"
    register: TEST

  - debug:
      var: TEST

  - debug:
      msg: "{{ TEST }}"

而只会得到 msg: "TEST" 而不是预期的:

TASK [debug] **************************
ok: [localhost] =>
  TEST:
    changed: true
    cmd: echo something
    delta: '0:00:00.012925'
    end: '2023-05-24 12:00:00.856922'
    failed: false
    msg: ''
    rc: 0
    start: '2023-05-24 12:00:00.843997'
    stderr: ''
    stderr_lines: []
    stdout: something
    stdout_lines:
    - something

TASK [debug] **************************
ok: [localhost] =>
  msg:
    changed: true
    cmd: echo something
    delta: '0:00:00.012925'
    end: '2023-05-24 12:00:00.856922'
    failed: false
    msg: ''
    rc: 0
    start: '2023-05-24 12:00:00.843997'
    stderr: ''
    stderr_lines: []
    stdout: something
    stdout_lines:
    - something

> 为什么我只获取到了...变量名而没有实际的...内容?

我可以通过变量优先级以及使用--extra-vars调用一个最小示例剧本来产生你的行为。

> 一般来说,Ansible会优先考虑最近定义、最活跃、作用域最明确的变量。

在你的情况下:

ansible-playbook debug.yml --extra-vars="test_value=test_value"

或在我的情况下:

ansible-playbook debug.yml --extra-vars="TEST=TEST"

会得到以下输出:

TASK [debug] *****
ok: [localhost] =>
  msg: test_value

或者

TASK [debug] *****
ok: [localhost] =>
  msg: TEST

但这意味着你的案例描述缺少重要信息或者是误导性的。

总的来说,注册变量的内容是显示出来的。它可能看起来像变量名,但实际上是与变量名“相同的内容”。

如果这确实是情况,你可能需要在源代码中搜索这样的出现,例如:~/test$ grep -Rn test_value .

英文:

According Return Values

> Ansible modules normally return a data structure that can be registered into a variable ...

and Registering variables

> Registered variables may be simple variables, list variables, dictionary variables, or complex nested data structures. The documentation for each module includes a RETURN section describing the return values for that module.

in your case shell module – Execute shell commands on targets - Return Values.

> I am only getting the registered variable name and not actually the stdout contents?

As you can see from your output

"stdout": "something", "stdout_lines": ["something"]

you should get it via

- name: Output test value
  ansible.builtin.debug:
    var: test_value

- name: Output test value
  ansible.builtin.debug:
    var: test_value.stdout

For me it is not possible to produce a behavior where a minimal example playbook

---
- hosts: localhost
  become: false
  gather_facts: false

  tasks:

  - shell:
      cmd: "echo something"
    register: TEST

  - debug:
      var: TEST

  - debug:
      msg: "{{ TEST }}"

would just "msg": "TEST" instead of the expected

TASK [debug] **************************
ok: [localhost] =>
  TEST:
    changed: true
    cmd: echo something
    delta: '0:00:00.012925'
    end: '2023-05-24 12:00:00.856922'
    failed: false
    msg: ''
    rc: 0
    start: '2023-05-24 12:00:00.843997'
    stderr: ''
    stderr_lines: []
    stdout: something
    stdout_lines:
    - something

TASK [debug] **************************
ok: [localhost] =>
  msg:
    changed: true
    cmd: echo something
    delta: '0:00:00.012925'
    end: '2023-05-24 12:00:00.856922'
    failed: false
    msg: ''
    rc: 0
    start: '2023-05-24 12:00:00.843997'
    stderr: ''
    stderr_lines: []
    stdout: something
    stdout_lines:
    - something

> Why is it that I am only getting the ... variable name and not actually the ... contents?

I am able to produce your behavior via variable precedence and calling a minimal example playbook with --extra-vars to always win precedence

> In general, Ansible gives precedence to variables that were defined more recently, more actively, and with more explicit scope.

in your case

ansible-playbook debug.yml --extra-vars="test_value=test_value"

or in my case

ansible-playbook debug.yml --extra-vars="TEST=TEST"

resulting into an output of

TASK [debug] *****
ok: [localhost] =>
  msg: test_value

or

TASK [debug] *****
ok: [localhost] =>
  msg: TEST

but that would mean the description of your case is missing important information or is misleading.

Whatever, still, the content of the registered variable is displayed. It might look like the variable name but it is the content which is "the same as" the variable name.

If that is really the case you may need to search for such occurrences within your source code, in example ~/test$ grep -Rn test_value .

huangapple
  • 本文由 发表于 2023年5月24日 18:00:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76322293.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定