Ansible中从Cisco输出提取状态为down的以太网接口名
问题分析与解决方案
核心问题
你的interface_details返回空数组,原因如下:
- 将数据写入
output.json后,用lookup('file')读取的结果是JSON字符串,而非可直接操作的列表对象。map('flatten')只能处理列表/嵌套列表,对字符串执行此操作会返回空结果。 - 原流程冗余,无需将数据写入文件再读取,直接从
command_output.results处理即可。
修复后的Playbook
以下是简化并修复后的Playbook,直接提取状态为down的以太网接口名称,并输出JSON格式结果:
- name: Set global device name set_fact: global_device_name: "{{ device_name }}" - name: Execute command on interfaces cisco.ios.ios_command: commands: - "show interface {{ item }} brief" loop: "{{ hostvars[global_device_name]['ports'] }}" delegate_to: "{{ global_device_name }}" register: command_output changed_when: false - name: Extract down interfaces set_fact: down_interfaces: "{{ down_interfaces | default([]) + [item.item] }}" loop: "{{ command_output.results }}" when: "'down' in item.stdout_lines | select('match', '^Eth\\d+/\\d+') | first" - name: Output down interfaces as JSON debug: msg: "{{ down_interfaces | to_json }}" # 可选:将结果保存到JSON文件 - name: Save down interfaces to file copy: content: "{{ down_interfaces | to_nice_json }}" dest: down_interfaces.json
关键改进说明
- 直接处理命令结果:跳过写入/读取文件的冗余步骤,直接从
command_output.results中提取数据。 - 精准过滤down接口:
- 用
select('match', '^Eth\\d+/\\d+')筛选出包含接口名称的行(匹配EthX/X格式) - 检查该行是否包含
down关键字,确认接口状态
- 用
- 直接生成JSON:通过
to_json或to_nice_json直接将结果转换为JSON格式,无需额外处理。
高效替代方案(批量获取接口状态)
如果路由器支持,建议使用show interfaces status批量获取所有接口状态,避免循环执行命令,提升效率:
- name: Get all interface statuses cisco.ios.ios_command: commands: - "show interfaces status" delegate_to: "{{ global_device_name }}" register: all_interface_status changed_when: false - name: Extract down Ethernet interfaces set_fact: down_interfaces: "{{ all_interface_status.stdout[0] | regex_findall('^Eth\\d+/\\d+\\s+.*down', multiline=True) | map('regex_replace', '^(Eth\\d+/\\d+).*', '\\1') | list }}" - name: Output down interfaces as JSON debug: msg: "{{ down_interfaces | to_json }}"
此方案通过正则表达式直接从批量输出中提取所有状态为down的以太网接口,接口数量较多时优势明显。
内容的提问来源于stack exchange,提问作者Vinny
相关产品推荐
相关产品推荐

