如何将多远程服务器输出存入字典并导出文件(含扩展问题)
Ansible 主机数据收集与导出问题解决
初始问题与解决
需求是收集所有主机的补丁信息(示例用grep VERSION_ID /etc/os-release模拟),保存为字典并导出。初始Playbook合并字典时出现AnsibleUndefined错误,现已解决字典生成问题,当前可生成如下结构的字典:
ok: [hostname01] => { "fmap | dict2items": [ { "key": "hostname01", "value": "3Q2022" }, ... ] }
扩展问题与解决方案
1. 给字典添加更多属性
要在字典中加入bundle_before_patching、bundle_after_patching、was_server_rebooted等属性,需先在每个主机上收集对应数据,再生成包含多属性的子字典,最后合并到全局字典中。
示例Playbook片段:
- hosts: all gather_facts: False tasks: # 收集补丁前的bundle信息 - name: 获取补丁前版本 shell: "your_command_to_get_before_bundle" register: bundle_before # 收集补丁后的bundle信息 - name: 获取补丁后版本 shell: "your_command_to_get_after_bundle" register: bundle_after # 检查主机是否需要/已重启 - name: 检查重启状态 stat: path: /var/run/reboot-required register: reboot_status # 生成当前主机的多属性字典 - set_fact: host_patch_data: bundle_before_patching: "{{ bundle_before.stdout }}" bundle_after_patching: "{{ bundle_after.stdout }}" was_server_rebooted: "{{ reboot_status.stat.exists }}" # 在localhost合并所有主机数据 - name: 合并全局补丁信息字典 set_fact: final_patch_map: "{{ final_patch_map | default({}) | combine({inventory_hostname: host_patch_data}) }}" delegate_to: localhost run_once: true # 查看合并后的结果 - name: 显示全局字典 debug: var: final_patch_map delegate_to: localhost run_once: true
最终final_patch_map的结构为:
{ "hostname01": { "bundle_before_patching": "2Q2022", "bundle_after_patching": "3Q2022", "was_server_rebooted": true }, "hostname02": { ... } }
2. 将字典导出为CSV文件
之前用copy模块循环写入会导致文件被反复覆盖,最终只保留最后一条数据。正确做法是先将字典转换为CSV格式的完整字符串,再一次性写入文件。
针对单属性字典(如初始的主机+bundle)
- name: 生成CSV内容 set_fact: csv_content: | hostname,bundle {% for item in fmap | dict2items %} {{ item.key }},{{ item.value }} {% endfor %} delegate_to: localhost run_once: true - name: 写入CSV文件 copy: content: "{{ csv_content }}" dest: "./patch_report.csv" delegate_to: localhost run_once: true
针对多属性字典(如带多个补丁信息)
- name: 生成多属性CSV内容 set_fact: csv_content: | hostname,bundle_before_patching,bundle_after_patching,was_server_rebooted {% for host_item in final_patch_map | dict2items %} {{ host_item.key }},{{ host_item.value.bundle_before_patching }},{{ host_item.value.bundle_after_patching }},{{ host_item.value.was_server_rebooted }} {% endfor %} delegate_to: localhost run_once: true - name: 写入多属性CSV文件 copy: content: "{{ csv_content }}" dest: "./detailed_patch_report.csv" delegate_to: localhost run_once: true
生成的CSV格式如下:
hostname,bundle_before_patching,bundle_after_patching,was_server_rebooted hostname01,2Q2022,3Q2022,True hostname02,1Q2023,2Q2023,False
内容的提问来源于stack exchange,提问作者andrew
相关产品推荐
相关产品推荐

