如何在Ansible中将Zabbix配置命令输出转换为字典?
问题描述
我正在解析Zabbix配置文件以提取变量,本来可以拆分成多个独立任务完成,但我想在单个任务里实现。需要把命令输出转换成字典,请问该如何从文件中注册这些变量?
我的Ansible角色任务文件如下:
# tasks file for roles/test - name: Read vars shell: egrep -v -e "^#|^$" /etc/zabbix/zabbix_agentd.conf register: zbaconfig - name: Debug 1 debug: msg: - "{{ zbaconfig.stdout_lines }}" - name: Register vars set_fact: zba: "{{ dict(zbaconfig.stdout | split('\\n') | select() | map('split','=') | list) }}" - name: Debug 2 debug: msg: - "{{ zba.Hostname }}" - "{{ zba.ServerActive }}" - "{{ zba.Server }}"
执行后报错信息如下:
TASK [test : Debug 1] ok: [10.100.0.52] => { "msg": [ [ "PidFile=/run/zabbix/zabbix_agentd.pid", "LogFile=/var/log/zabbix/zabbix_agentd.log", "LogFileSize=0", "Server=zabbix.domain.com.ua", "ServerActive=zabbix.domain.com.ua", "Hostname=vs-net-dk01", "Include=/etc/zabbix/zabbix_agentd.d/*.conf" ], TASK [test : Register vars] fatal: [10.100.0.52]: FAILED! => {"msg": "template error while templating string: no filter named 'split'. String: {{ dict(zbaconfig.stdout | split('\n') | select() | map('split','=') | list) }}"}
解决方案
报错核心原因是Jinja2模板中不存在split过滤器,正确的做法是使用字符串原生的split()方法,或者直接利用shell模块返回的stdout_lines字段(该字段已自动将输出按换行分割为列表)。
最简修改方案
直接修改Register vars任务,利用已有的stdout_lines:
- name: Register vars set_fact: zba: "{{ dict(zbaconfig.stdout_lines | map('split', '=') | list) }}"
说明:
zbaconfig.stdout_lines已经是过滤掉空行和注释后的行列表(因为shell命令用了egrep -v "^#|^$"),无需额外过滤空行。map('split', '=')将每一行按=分割为键值对子列表。dict()将子列表转换为字典,之后即可通过zba.Hostname这类方式直接访问配置项。
处理含多个=的配置行
如果配置值中包含=(比如自定义参数),可以限制仅分割第一个=,避免破坏值的完整性:
- name: Register vars set_fact: zba: "{{ dict(zbaconfig.stdout_lines | map('split', '=', 1) | list) }}"
更符合Ansible最佳实践的方案
无需依赖目标主机的egrep命令,用slurp模块读取文件后本地处理:
- name: Read remote Zabbix config slurp: src: /etc/zabbix/zabbix_agentd.conf register: zbaconfig_raw - name: Parse config to dict set_fact: zba: >- {{ dict( zbaconfig_raw.content | b64decode | split('\n') | reject('match', '^#') | reject('match', '^$') | map('split', '=', 1) | list ) }}
内容的提问来源于stack exchange,提问作者Андрей Курочкин
相关产品推荐
相关产品推荐

