You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中合并同键字典生成全局服务器列表

如何在Ansible中将多台服务器的独立字典合并为全局字典?

问题背景

我正在用Ansible完成一项任务,已经通过以下playbook为每台服务器生成了包含Servername、IP-Adresse、OS、Plattform字段的server_list字典:

- name: Create and Add items to server_list
  set_fact: 
    server_list: "{{ server_list | default({}) | combine ({ item.key : item.value }) }}"
  with_items:
    - { 'key': 'Servername' , 'value': "{{ ansible_hostname }}"}
    - { 'key': 'IP-Adresse' , 'value': "{{ ansible_default_ipv4.address }}"}
    - { 'key': 'OS' , 'value': "{{ ansible_os_family }} {{ ansible_distribution_major_version }}"}
    - { 'key': 'Plattform' , 'value': "{{ ansible_system }}"}

- name: DEBUG server_list
  debug:
    var=server_list

当前每台服务器会输出独立的server_list字典,示例如下:

ok: [XXX] => {
    "server_list": {
        "IP-Adresse": "x.x.x.x",
        "OS": "Debian 11",
        "Plattform": "Linux",
        "Servername": "XXX"
    }
}
ok: [YYY] => {
    "server_list": {
        "IP-Adresse": "x.x.x.y",
        "OS": "Debian 11",
        "Plattform": "Linux",
        "Servername": "YYY"
    }
}

我需要将这些字典合并为一个全局的server_list_dict,格式示例如下:

{
    "server_list_dict": {
        "0": {
            "Servername": "XXX",
            "IP-Adresse": "x.x.x.x",
            "OS": "Debian 11",
            "Plattform": "Linux"
        },
        "1": {
            "Servername": "YYY",
            "IP-Adresse": "x.x.x.y",
            "OS": "Debian 11",
            "Plattform": "Linux"
        }
    }
}

后续计划用这个全局字典通过以下模板生成服务器信息HTML表格:

<table style="width:100%">
  <!-- table header -->
  {% if server_list_dict %}
  <tr>
     {% for key in server_list_dict[0] %}
     <th> {{ key }} </th>
     {% endfor %}
  </tr>
  {% endif %}

  <!-- table rows -->
  {% for dict_item in server_list_dict %}
  <tr>
     {% for value in dict_item.values() %}
     <td> {{ value }} </td>
     {% endfor %}
  </tr>
  {% endfor %}
</table>

解决方案

核心思路是收集所有主机上的server_list变量,在控制节点组装成全局字典,以下是两种可行实现方式:

方法1:一步生成带数字索引的全局字典

在原playbook末尾添加以下任务,通过delegate_to: localhost指定任务在控制节点执行,避免远程服务器重复操作:

- name: 收集所有主机信息并生成全局字典
  delegate_to: localhost
  set_fact:
    server_list_dict: "{{ dict( range(0, groups['all'] | length ) | map('string'), groups['all'] | map('extract', hostvars, 'server_list') ) }}"
  run_once: true

代码说明:

  • groups['all']:获取所有目标主机的列表
  • map('extract', hostvars, 'server_list'):从每台主机的hostvars中提取server_list字典,生成包含所有服务器信息的列表
  • range(0, groups['all'] | length ) | map('string'):生成从0开始的字符串类型索引(如"0"、"1")
  • dict(...):将索引列表与服务器信息列表配对,生成符合要求的全局字典

方法2:分步实现(逻辑更直观)

如果觉得一步写法过于紧凑,可以拆分为两步:

# 第一步:收集所有主机的server_list为列表
- name: 收集所有主机信息到临时列表
  delegate_to: localhost
  set_fact:
    server_list_temp: "{{ groups['all'] | map('extract', hostvars, 'server_list') | list }}"
  run_once: true

# 第二步:将列表转换为带数字键的全局字典
- name: 将列表转换为全局字典
  delegate_to: localhost
  set_fact:
    server_list_dict: "{{ dict( server_list_temp | indices | map('string'), server_list_temp ) }}"
  run_once: true

代码说明:

  • server_list_temp:先将所有服务器的server_list收集为普通列表,格式为[ {服务器1信息}, {服务器2信息}, ... ]
  • server_list_temp | indices:获取列表的索引(0、1、2...),转换为字符串后与列表元素配对生成字典

验证结果

添加以下debug任务可查看最终生成的全局字典:

- name: 验证全局server_list_dict
  delegate_to: localhost
  debug:
    var: server_list_dict
  run_once: true

执行后即可得到符合要求的全局字典,之后可直接在模板中使用server_list_dict变量生成HTML表格。

内容的提问来源于stack exchange,提问作者marcb4

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 06:48:09