在Ansible中从文件执行某些主机上的命令

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

Executing a command in ansible on some hosts from a file

问题

Here's the translated part of your text:

我有一个主机组的清单

[group 1]
host1
host2

[group 2]
host1
host2
host3
host4
host5

host1有一个JSON文件,其中包含一些对象的列表,例如:

[{"hostName": "host2"}, {"hostName": "host4"}]

或者可能只有一个主机

[{"hostName": "host1"}]

我需要从Ansible中读取此文件并仅在此文件中的主机上执行命令

读取文件

  • name: 读取 /tmp/hosts.json
    shell: "/tmp/hosts.json | jq '.[].hostName'"
    register: data
    when:

    • inventory_hostname == groups['group1'][0]

我正常地获得了结果

  • name: T14
    debug: msg="data - {{ data | to_nice_json }}"
    when:

    • inventory_hostname == groups['group1'][0]

ok: [host1] =>
msg: |-
data - {
"changed": true,
"cmd": "/tmp/hosts.json | jq '.[].hostName'",
"delta": "0:00:00.036695",
"end": "2023-06-14 22:39:20.125326",
"failed": false,
"msg": "",
"rc": 0,
"start": "2023-06-14 22:39:20.088631",
"stderr": "",
"stderr_lines": [],
"stdout": ""host4"",
"stdout_lines": [
""host4""
]
}

我无法弄清楚如何进一步处理这个列表以执行我的命令,比如:

  • name: 命令
    shell: "ls /tmp"
    when:

    • inventory_hostname == date.standard output....

您有任何关于如何执行此操作的想法吗?

(Note: The code portions are not translated as per your request.)

英文:

I have a group of hosts in the inventory

[group 1]
host1
host2

[group 2]
host1
host2
host3
host4
host5

hoste1 has a json file with a list of some objects, example:

[ { "hostName": "host2"}, { "hostName": "host4"}]

or maybe one host

[ { "hostName": "host1"}]

I need to read this file from ansible and execute the command only on hosts from this file

Reading the file

- name: Read /tmp/hosts.json
  shell: "/tmp/hosts.json | jq '.[].hostName'"
  register: data
  when:
    - inventory_hostname == groups['group1'][0]

I get the result normally

- name: T14
  debug: msg="data - {{ data | to_nice_json }}"
  when:
    - inventory_hostname == groups['group1'][0]


ok: [host1] => 
  msg: |-
    data - {
        "changed": true,
        "cmd": "/tmp/hosts.json | jq '.[].hostName'",
        "delta": "0:00:00.036695",
        "end": "2023-06-14 22:39:20.125326",
        "failed": false,
        "msg": "",
        "rc": 0,
        "start": "2023-06-14 22:39:20.088631",
        "stderr": "",
        "stderr_lines": [],
        "stdout": "\"host4\"",
        "stdout_lines": [
            "\"host4\""
        ]
    }

I can't figure out how to further process this list in order to execute my command, let's say:

- name: Command
  shell: "ls /tmp"
  when:
    - inventory_hostname == date.standard output....

Do you have any ideas how to do this?

答案1

得分: 2

以下是您要翻译的内容:

Given the file at host1

shell> ssh admin@host1 cat /tmp/hosts.json
[{"hostName": "host1"}, {"hostName": "host3"}]

Read the file

    - block:
        - command: cat /tmp/hosts.json
          register: out
        - set_fact:
            data: "{{ out.stdout|from_yaml|map(attribute='hostName') }}"
      when: inventory_hostname == groups.group1.0
      run_once: true

This will create the list of data for all hosts when you set run_once: true

    - debug:
        var: data

gives abridged

TASK [debug] **********************************************************************************
ok: [host2] => 
  data:[host1, host3]
ok: [host1] => 
  data:[host1, host3]
ok: [host3] => 
  data:[host1, host3]
ok: [host5] => 
  data:[host1, host3]
ok: [host4] => 
  data:[host1, host3]

Now you can execute the command only on hosts from this file. For example,

    - block:
        - command: date
          register: out
        - debug:
            var: out.stdout
      when: inventory_hostname in data

gives

TASK [command] ********************************************************************************
skipping: [host2]
skipping: [host4]
skipping: [host5]
changed: [host1]
changed: [host3]

TASK [debug] **********************************************************************************
skipping: [host2]
ok: [host1] => 
  out.stdout: Thu Jun 15 04:24:28 UTC 2023
ok: [host3] => 
  out.stdout: Thu Jun 15 04:24:28 UTC 2023
skipping: [host4]
skipping: [host5]

Example of a complete playbook for testing

- hosts: all

  tasks:

    - block:
        - command: cat /tmp/hosts.json
          register: out
        - set_fact:
            data: "{{ out.stdout|from_yaml|map(attribute='hostName') }}"
      when: inventory_hostname == groups.group1.0
      run_once: true

    - debug:
        var: data|to_yaml

Use lookup pipe if you want to use jq to parse the data. For example, the set_fact below gives the same list of hosts data

        - set_fact:
            data: "{{ lookup('pipe', cmd).splitlines() }}"
          vars:
            cmd: "echo '{{ out.stdout }}' | jq -r '.[].hostName'"

英文:

Given the file at host1

shell> ssh admin@host1 cat /tmp/hosts.json
[{"hostName": "host1"}, {"hostName": "host3"}]

Read the file

    - block:
        - command: cat /tmp/hosts.json
          register: out
        - set_fact:
            data: "{{ out.stdout|from_yaml|map(attribute='hostName') }}"
      when: inventory_hostname == groups.group1.0
      run_once: true

This will create the list of data for all hosts when you set run_once: true

    - debug:
        var: data

gives abridged

TASK [debug] **********************************************************************************
ok: [host2] => 
  data:[host1, host3]
ok: [host1] => 
  data:[host1, host3]
ok: [host3] => 
  data:[host1, host3]
ok: [host5] => 
  data:[host1, host3]
ok: [host4] => 
  data:[host1, host3]

Now you can execute the command only on hosts from this file. For example,

    - block:
        - command: date
          register: out
        - debug:
            var: out.stdout
      when: inventory_hostname in data

gives

TASK [command] ********************************************************************************
skipping: [host2]
skipping: [host4]
skipping: [host5]
changed: [host1]
changed: [host3]

TASK [debug] **********************************************************************************
skipping: [host2]
ok: [host1] => 
  out.stdout: Thu Jun 15 04:24:28 UTC 2023
ok: [host3] => 
  out.stdout: Thu Jun 15 04:24:28 UTC 2023
skipping: [host4]
skipping: [host5]

<hr>

<sup>

Example of a complete playbook for testing

- hosts: all

  tasks:

    - block:
        - command: cat /tmp/hosts.json
          register: out
        - set_fact:
            data: &quot;{{ out.stdout|from_yaml|map(attribute=&#39;hostName&#39;) }}&quot;
      when: inventory_hostname == groups.group1.0
      run_once: true

    - debug:
        var: data|to_yaml

    - block:
        - command: date
          register: out
        - debug:
            var: out.stdout
      when: inventory_hostname in data

<hr>

Use lookup pipe if you want to use jq to parse the data. For example, the set_fact below gives the same list of hosts data

        - set_fact:
            data: &quot;{{ lookup(&#39;pipe&#39;, cmd).splitlines() }}&quot;
          vars:
            cmd: &quot;echo &#39;{{ out.stdout }}&#39; | jq -r &#39;.[].hostName&#39;&quot;

</sup>

huangapple
  • 本文由 发表于 2023年6月15日 11:32:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/76478909.html
匿名

发表评论

匿名网友

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

确定