Ansible脚本报错:无法将异常主机列表写入本地/tmp目录
解决Ansible收集异常主机并写入本地文件的问题
问题根源
- 变量未初始化:当所有主机都正常时,
problematic_hosts变量从未被创建,导致写入文件任务因变量未定义报错。 - 不可达主机未被收集:不可达主机(如示例中的machine3)不会执行任何任务,包括
set_fact,因此这类主机不会被加入异常列表。 - 条件判断不严谨:当主机不可达时,
service_status变量不存在,直接判断service_status.stdout会引发潜在错误。
修复后的Ansible脚本
--- - name: Check tractor-blade service and connectivity hosts: linux_machines gather_facts: no vars: # 初始化空列表,避免变量未定义报错 problematic_hosts: [] tasks: - name: Check host connectivity ping: register: ping_result ignore_errors: yes - name: Check test-serv service status shell: systemctl is-active test-serv register: service_status ignore_errors: yes # 仅在主机可达时执行服务检查 when: ping_result is success - name: Collect all problematic hosts (including unreachable) set_fact: problematic_hosts: "{{ problematic_hosts + [host] }}" # 遍历inventory中所有主机,包括不可达的 loop: "{{ ansible_play_hosts_all }}" when: > # 捕获不可达主机 hostvars[host].ansible_unreachable | default(false) or # 捕获ping失败的主机 (hostvars[host].ping_result is defined and hostvars[host].ping_result is failed) or # 捕获服务未运行的主机 (hostvars[host].service_status is defined and hostvars[host].service_status.stdout != 'active') # 仅执行一次,避免重复收集 run_once: true - name: Write problematic hosts to local /tmp file copy: content: "{{ problematic_hosts | join('\n') }}" dest: /tmp/problematic_hosts.txt # 委托到本地执行 delegate_to: localhost run_once: true
关键修改说明
- 初始化变量:在play的
vars段预先定义problematic_hosts为空列表,确保变量始终存在,即使没有异常主机也不会报错。 - 全主机遍历:使用
ansible_play_hosts_all遍历inventory中的所有主机,包括不可达的,避免遗漏这类主机。 - 严谨的条件判断:
- 用
hostvars[host].ansible_unreachable直接识别不可达主机 - 对
ping_result和service_status增加is defined判断,避免变量不存在引发的错误
- 用
- 清晰的本地执行:用
delegate_to: localhost替代local_action,语法更直观。
效果验证
执行修复后的脚本后:
- 不可达主机(如machine3)会被加入异常列表
- 服务未运行的主机会被正确识别
- 即使没有异常主机,
/tmp/problematic_hosts.txt会被创建为空白文件,不会出现变量未定义的报错
内容的提问来源于stack exchange,提问作者ARthur
相关产品推荐
相关产品推荐

